คำอธิบายประกอบ (หรือที่เรียกว่าข้อมูลเมตา) เป็นวิธีที่เป็นทางการสำหรับเราในการเพิ่มข้อมูลในรหัสของเราทำให้เราสามารถใช้ข้อมูลนี้ได้อย่างสะดวกสบายในเวลาต่อมา
1. ไวยากรณ์พื้นฐาน
Java SE5 มีสามคำอธิบายประกอบมาตรฐานในตัว
@Override: ระบุว่าคำนิยามวิธีการปัจจุบันจะเขียนทับวิธีการใน superclass หากคุณสะกดการสะกดผิดโดยไม่ตั้งใจหรือลายเซ็นวิธีการไม่ตรงกับวิธีที่เขียนทับคอมไพเลอร์จะออกข้อความแสดงข้อผิดพลาด
@Deprecated: หากโปรแกรมเมอร์ใช้องค์ประกอบที่มีคำอธิบายประกอบคอมไพเลอร์จะออกข้อความเตือน
@supperesswarnings: ปิดข้อความเตือนคอมไพเลอร์ที่ไม่เหมาะสม
Java SE5 มีคำอธิบายประกอบเมตาในตัวสี่รายการ
@Target: ระบุว่าสามารถใช้คำอธิบายประกอบนี้ได้ที่ไหน พารามิเตอร์ elementType ที่เป็นไปได้รวมถึง:
1) ตัวสร้าง: คำสั่งของตัวสร้าง
2) ฟิลด์: การประกาศโดเมน (รวมถึงอินสแตนซ์ enum)
3) local_variable: การประกาศตัวแปรท้องถิ่น
4) วิธีการ: คำสั่งวิธีการ
5) แพ็คเกจ: คำสั่งแพ็คเกจ
6) พารามิเตอร์: การประกาศพารามิเตอร์
7) ประเภท: คลาสอินเตอร์เฟส (รวมถึงประเภทคำอธิบายประกอบ) หรือการประกาศ enum
@Retention: ระบุในระดับใดที่จะบันทึกข้อมูลคำอธิบายประกอบ พารามิเตอร์การเก็บรักษาแบบเสริม ได้แก่ :
1) แหล่งที่มา: คำอธิบายประกอบจะถูกทิ้งโดยคอมไพเลอร์
2) คลาส: คำอธิบายประกอบมีอยู่ในไฟล์คลาส แต่จะถูกทิ้งโดย VM
3) รันไทม์: VM จะยังคงมีคำอธิบายประกอบในระหว่างการรันไทม์ดังนั้นข้อมูลคำอธิบายประกอบสามารถอ่านได้ผ่านกลไกการสะท้อนกลับ
@Documented: รวมคำอธิบายประกอบนี้ใน javadoc
@Inherited: อนุญาตให้คลาสย่อยเพื่อสืบทอดคำอธิบายประกอบในชั้นเรียนหลักเกือบตลอดเวลาโปรแกรมเมอร์ส่วนใหญ่กำหนดคำอธิบายประกอบของตัวเองและเขียนโปรเซสเซอร์ของตัวเองเพื่อจัดการกับพวกเขา
usecase.java
แพ็คเกจ com; นำเข้า java.lang.annotation.ElementType; นำเข้า java.lang.annotation.retention; นำเข้า java.lang.annotation.RetentionPolicy; นำเข้า java.lang.annotation.target; @Target (ElementType.method) // ใช้เพื่อกำหนดตำแหน่งที่คำอธิบายประกอบของคุณจะถูกนำไปใช้และสิ่งนี้จะถูกนำไปใช้เป็นวิธี // ใช้เพื่อกำหนดระดับที่คำอธิบายประกอบมีอยู่ในซอร์สโค้ด (คลาส) หรือรันไทม์ (รันไทม์) @Retention คำอธิบายสตริงสาธารณะ () ค่าเริ่มต้น "ไม่มีคำอธิบาย"; } PasswordUtils .Java Package com; คลาสสาธารณะ PasswordUtils {@USECASE (ID = 47, DESCRIPTION = "รหัสผ่านต้องมีอย่างน้อยหนึ่งตัวเลข") Public Boolean ValidatePassword () {return True; } @USECASE (ID = 48) สตริงสาธารณะ EncryptPassword (รหัสผ่านสตริง) {ส่งคืนรหัสผ่าน; } @USECASE (ID = 49, คำอธิบาย = "JONG_CAI") โมฆะสาธารณะ sholdame () {System.out.println ("JONG_CAI"); -
2. เขียนโปรเซสเซอร์คำอธิบายประกอบ
หากไม่มีเครื่องมือในการอ่านคำอธิบายประกอบคำอธิบายประกอบจะไม่มีประโยชน์มากกว่าคำอธิบายประกอบ ในกระบวนการใช้คำอธิบายประกอบส่วนสำคัญคือการสร้างและใช้โปรเซสเซอร์คำอธิบายประกอบ Java SE5 ขยายกลไกการสะท้อน API เพื่อช่วยให้โปรแกรมเมอร์สร้างเครื่องมือดังกล่าว ในเวลาเดียวกันมันยังมีเครื่องมือภายนอกที่เหมาะสมเพื่อช่วยโปรแกรมเมอร์แยกวิเคราะห์ซอร์สโค้ด Java ด้วยคำอธิบายประกอบ ด้านล่างเป็นโปรเซสเซอร์คำอธิบายประกอบที่ง่ายมากซึ่งเราจะใช้ในการอ่านคลาส PasswordUtils และใช้กลไกการสะท้อนกลับเพื่อค้นหาแท็ก @USECASE เราจัดเตรียมไว้ด้วยชุดของค่า ID จากนั้นจะแสดงรายการกรณีการใช้งานที่พบใน PasswordUtils รวมถึงกรณีการใช้งานที่ขาดหายไป
usecasetracker.java แพ็คเกจ com; นำเข้า java.lang.reflect.method; นำเข้า java.util.arraylist; นำเข้า Java.util.Collections; นำเข้า java.util.list; ชั้นเรียนสาธารณะ usecasetracker {โมฆะสาธารณะคงที่ trackusecases (รายการ <จำนวนเต็ม> รายการ, คลาส <s?> cl) {สำหรับ (วิธี m: cl.getdeclaredmethods ()) {usecase us = m.getannotation (usecase.class); if (us! = null) {system.out.println ("พบกรณีใช้:" + us.id () + "" + us.description ()); list.remove (จำนวนเต็มใหม่ (us.id ())); }} สำหรับ (int i: list) {system.out.println ("คำเตือน: ขาดหายไป-" + i); }} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {รายการ <integer> list = new ArrayList <integer> (); คอลเลกชัน ADDALL (รายการ, 47,48,49,50,51); trackusecases (รายการ, passwordUtils.class); -
โปรแกรมนี้ใช้วิธีการสะท้อนสองวิธี: getDeclaredMethods () และ getAnnotation () พวกเขาทั้งคู่อยู่ในอินเทอร์เฟซ AnnotatedElement (คลาส, วิธีการและฟิลด์และคลาสอื่น ๆ ใช้อินเทอร์เฟซนี้) วิธี getannotation () ส่งคืนวัตถุคำอธิบายประกอบของประเภทที่ระบุซึ่งเป็น USECASE หากวิธีการใส่คำอธิบายประกอบไม่มีคำอธิบายประกอบของประเภทมันจะส่งคืนค่า NULL จากนั้นเราแยกค่าขององค์ประกอบจากวัตถุ USECASE ที่ส่งคืนโดยเรียกใช้ ID () และคำอธิบาย () วิธีการเข้ารหัส Passpassword () ไม่ได้ระบุค่าคำอธิบายเมื่อมีคำอธิบายประกอบดังนั้นเมื่อโปรเซสเซอร์ประมวลผลคำอธิบายประกอบที่สอดคล้องกันค่าเริ่มต้นของวิธีคำอธิบาย () จะได้รับโดยวิธีคำอธิบาย ()
คำอธิบายประกอบกำลังแพร่กระจายในโลกของชวา หากคุณมีเวลาเขียนบทความคำอธิบายประกอบแบบง่าย ๆ นี้ เป็นการแนะนำคำอธิบายประกอบ ฉันหวังว่าคุณจะสามารถโยนอิฐและเรียนรู้ร่วมกัน ...
หากคุณหยุดพูดเรื่องไร้สาระการฝึกฝนเป็นบรรทัดล่าง
3. ตัวอย่าง
มาพูดคุยเกี่ยวกับแนวคิดของคำอธิบายประกอบก่อนแล้วพูดคุยเกี่ยวกับวิธีการออกแบบคำอธิบายประกอบของคุณเอง
ก่อนอื่นในแพ็คเกจ java.lang.annotation ที่มาพร้อมกับ JDK เปิดไฟล์ต้นฉบับต่อไปนี้:
File Source File Target.java
@Documented @Retention (RETINGINTPOLICY.RUNTIME) @TARGET (ElementType.Annotation_type) เป้าหมายสาธารณะ @Interface เป้าหมาย {ElementType [] ค่า (); @Documented @Retention (RETINGINTPOLICY.RUNTIME) @TARGET (ElementType.Annotation_type) เป้าหมายสาธารณะ @Interface เป้าหมาย {ElementType [] ค่า (); -
@Interface เป็นคำหลัก เมื่อออกแบบคำอธิบายประกอบประเภทจะต้องกำหนดเป็น @Interface และคุณไม่สามารถใช้คำหลักคลาสหรืออินเทอร์เฟซ (คุณจะคิดว่าดวงอาทิตย์นั้นค่อนข้างตระหนี่ แต่มันดูคล้ายกับอินเทอร์เฟซ)
การเก็บรักษาไฟล์แหล่งที่มา java
@Documented @Retention (RETINGINTPOLICY.RUNTIME) @TARGET (ElementType.Annotation_Type) การเก็บรักษาสาธารณะ @Interface retention {มูลค่าการรักษา (); } @documented @retention (RetentionPolicy.runtime) @Target (ElementType.Annotation_type) การเก็บรักษาสาธารณะ @interface retention {มูลค่าการเก็บรักษา (); -
หลังจากเห็นสิ่งนี้คุณอาจคลุมเครือและไม่รู้ว่าคุณกำลังพูดถึงอะไร ไม่ต้องกังวลลองดู ไฟล์ข้างต้นใช้สองฟิลด์ RetentionPolicy และ ElementType และคุณอาจเดาได้ว่านี่เป็นไฟล์ Java สองไฟล์ อันที่จริงแล้วซอร์สโค้ดของไฟล์ทั้งสองนี้มีดังนี้:
แหล่งข้อมูลแหล่งที่มา
Public Enum RetentionPolicy {Source, Class, Runtime} Public Enum RetentionPolicy {แหล่งที่มา, คลาส, รันไทม์} นี่คือประเภท enum ที่มีสามค่าคือแหล่งที่มาคลาสและรันไทม์
แหล่งที่มาหมายความว่าข้อมูลประเภทคำอธิบายประกอบจะถูกเก็บไว้ในซอร์สโค้ดโปรแกรมเท่านั้น หากรวบรวมซอร์สโค้ดข้อมูลคำอธิบายประกอบจะหายไปและจะไม่ถูกเก็บไว้ในไฟล์. class ที่รวบรวม
คลาสหมายความว่าข้อมูลประเภทคำอธิบายประกอบจะถูกเก็บไว้ในซอร์สโค้ดโปรแกรมและจะถูกเก็บไว้ในไฟล์. class ที่รวบรวม เมื่อดำเนินการข้อมูลนี้จะไม่ถูกโหลดลงในเครื่องเสมือน (JVM) โปรดทราบว่าเมื่อคุณไม่ได้ตั้งค่าการเก็บรักษาของประเภทคำอธิบายประกอบค่าเริ่มต้นของระบบคือคลาส
ที่สามคือรันไทม์ซึ่งหมายความว่าข้อมูลจะถูกเก็บไว้ในซอร์สโค้ดและรวบรวมไฟล์. class และข้อมูลนี้จะถูกโหลดลงใน JVM ในระหว่างการดำเนินการ
ตัวอย่างเช่นหากการเก็บรักษาใน @Override ถูกตั้งค่าเป็นแหล่งที่มาหากการรวบรวมสำเร็จคุณไม่ต้องการข้อมูลที่ตรวจสอบเหล่านี้ ในทางตรงกันข้ามการเก็บรักษาใน @Deprecated ถูกตั้งค่าเป็นรันไทม์ซึ่งหมายความว่านอกเหนือจากการเตือนเราว่าวิธีใดที่ใช้ในระหว่างการรวบรวมคุณยังสามารถตรวจสอบได้ว่าวิธีการเลิกใช้เมื่อดำเนินการหรือไม่
ไฟล์แหล่งที่มา ElementType.java
public enum elementType {ประเภท, ฟิลด์, วิธีการ, พารามิเตอร์, ตัวสร้าง, local_variable, Annotation_type, แพ็คเกจ} public enum elementType {ประเภท, ฟิลด์, วิธีการ, พารามิเตอร์, คอนสตรัคเตอร์, local_variable, Annotation_type, แพ็คเกจ} @ ElementType ในเป้าหมายถูกใช้เพื่อระบุประเภทขององค์ประกอบที่สามารถใช้งานได้ เรามาอธิบาย: ประเภท (ประเภท), ฟิลด์ (แอตทริบิวต์), เมธอด (เมธอด), พารามิเตอร์ (พารามิเตอร์), คอนสตรัคเตอร์ (ตัวสร้าง), local_variable (ตัวแปรท้องถิ่น), Annotation_type, แพ็คเกจ (แพ็คเกจ) โดยที่ประเภท (ประเภท) หมายถึงการใช้ในชั้นเรียน
นอกจากนี้ยังสามารถเห็นได้จากซอร์สโค้ด 1 ที่ @Target เองก็ใช้ตัวเองเพื่อประกาศตัวเองและสามารถใช้กับ Annotation_type เท่านั้น
หากประเภทคำอธิบายประกอบไม่ได้ระบุองค์ประกอบ @Target ที่ใช้จะใช้กับองค์ประกอบใด ๆ และองค์ประกอบที่นี่หมายถึงแปดประเภทข้างต้น
ให้ฉันยกตัวอย่างที่ถูกต้องให้คุณ:
@Target (ElementType.method)
@target (value = elementType.method)
@Target (ElementType.Method, ElementType.Constructor)
โปรดดูเอกสาร Javadoc สำหรับรายละเอียด
ไฟล์ต้นฉบับทั้งหมดใช้ @documented วัตถุประสงค์ของ @Documented คือการเปิดใช้งานข้อมูลประเภทคำอธิบายประกอบนี้ที่จะแสดงในเอกสารคำอธิบาย Javaapi; หากไม่ได้เพิ่มข้อมูลที่สร้างโดยประเภทนี้จะไม่พบเมื่อใช้ Javadoc เพื่อสร้างเอกสาร API
อีกประเด็นหนึ่งคือถ้าคุณต้องการสืบทอดข้อมูลคำอธิบายประกอบไปยังคลาสย่อยคุณจะใช้ประเภทคำอธิบายประกอบ @Inherited
ต่อไปนี้เป็นตัวอย่างคำอธิบายประกอบที่ง่ายที่สุดในการออกแบบซึ่งประกอบด้วยสี่ไฟล์
description.java
แพ็คเกจเบาลง javaeye.com; นำเข้า java.lang.annotation.documented; นำเข้า java.lang.annotation.ElementType; นำเข้า java.lang.annotation.retention; นำเข้า java.lang.annotation.RetentionPolicy; นำเข้า java.lang.annotation.target; @Target (ElementType.type) @retention (RetentionPolicy.runtime) @Documented สาธารณะ @Interface คำอธิบาย {ค่าสตริง (); } package light.javaeye.com; นำเข้า java.lang.annotation.documented; นำเข้า java.lang.annotation.ElementType; นำเข้า java.lang.annotation.retention; นำเข้า java.lang.annotation.RetentionPolicy; นำเข้า java.lang.annotation.target; @Target (ElementType.type) @retention (RetentionPolicy.runtime) @Documented สาธารณะ @Interface คำอธิบาย {ค่าสตริง (); -
หมายเหตุ: คำอธิบายประกอบทั้งหมดจะสืบทอดอินเทอร์เฟซ java.lang.annotation โดยอัตโนมัติดังนั้นคุณจึงไม่สามารถสืบทอดคลาสหรืออินเทอร์เฟซอื่น ๆ ได้
จุดที่สำคัญที่สุดคือวิธีการตั้งค่าพารามิเตอร์ในประเภทคำอธิบายประกอบ:
ก่อนอื่นคุณสามารถใช้สิทธิ์การเข้าถึงสาธารณะหรือเริ่มต้นเพื่อแก้ไขได้เท่านั้น ตัวอย่างเช่นค่าสตริง (); ที่นี่ตั้งค่าเมธอดเป็นประเภทเริ่มต้น
ประการที่สองสมาชิกพารามิเตอร์สามารถใช้ข้อมูลพื้นฐานแปดชนิดเท่านั้น: ไบต์, สั้น, ถ่าน, int, ยาว, ลอย, double, boolean และประเภทข้อมูลเช่นสตริง, enum, คลาส, คำอธิบายประกอบ, รวมถึงอาร์เรย์ของประเภทเหล่านี้ ตัวอย่างเช่นค่าสตริง (); สมาชิกพารามิเตอร์ที่นี่คือสตริง
ประการที่สามหากมีสมาชิกพารามิเตอร์เพียงคนเดียวจะเป็นการดีที่สุดที่จะตั้งชื่อพารามิเตอร์เป็น "ค่า" และเพิ่มวงเล็บในภายหลัง ตัวอย่าง: ตัวอย่างข้างต้นมีสมาชิกพารามิเตอร์เพียงหนึ่งคน
Name.java
แพ็คเกจเบาลง javaeye.com; นำเข้า java.lang.annotation.documented; นำเข้า java.lang.annotation.ElementType; นำเข้า java.lang.annotation.retention; นำเข้า java.lang.annotation.RetentionPolicy; นำเข้า java.lang.annotation.target; // โปรดทราบว่า @target ที่นี่แตกต่างจาก @description และสมาชิกพารามิเตอร์ก็แตกต่างกัน @Target (ElementType.method) @retention (RetentionPolicy.runtime) @Documented ชื่อสาธารณะ @interface {String Originate (); ชุมชนสตริง (); } package light.javaeye.com; นำเข้า java.lang.annotation.documented; นำเข้า java.lang.annotation.ElementType; นำเข้า java.lang.annotation.retention; นำเข้า java.lang.annotation.RetentionPolicy; นำเข้า java.lang.annotation.target; // โปรดทราบว่า @target ที่นี่แตกต่างจาก @description และสมาชิกพารามิเตอร์ก็แตกต่างกัน @Target (ElementType.method) @retention (RetentionPolicy.runtime) @Documented ชื่อสาธารณะ @interface {String Originate (); ชุมชนสตริง (); -
javaeyer.java
แพ็คเกจเบาลง javaeye.com; @Description ("javaeye, เป็นชุมชนแลกเปลี่ยนการพัฒนาซอฟต์แวร์ที่ดีที่สุด") คลาสสาธารณะ Javaeyer {@Name (Originate = "ผู้ก่อตั้ง: Robbin", Community = "Javaeye") สตริงสาธารณะ getName () {return null; } @Name (Originate = "ผู้ก่อตั้ง: Jiangnan Baiyi", Community = "Springside") Public String getName2 () {return "ยืม ID สองรหัสโปรดยกโทษให้ฉันสำหรับการเขียนตัวอย่างนี้!"; }} package light.javaeye.com; @Description ("javaeye, เป็นชุมชนแลกเปลี่ยนการพัฒนาซอฟต์แวร์ที่ดีที่สุด") คลาสสาธารณะ Javaeyer {@Name (Originate = "ผู้ก่อตั้ง: Robbin", Community = "Javaeye") สตริงสาธารณะ getName () {return null; } @Name (Originate = "ผู้ก่อตั้ง: Jiangnan Baiyi", Community = "Springside") Public String getName2 () {return "ยืม ID สองรหัสโปรดยกโทษให้ฉันสำหรับการเขียนตัวอย่างนี้!"; -เขียนคลาส testannotation ที่สามารถเรียกใช้ข้อมูล javaeyer สกัด
แพ็คเกจเบาลง javaeye.com; นำเข้า java.lang.reflect.method; นำเข้า java.util.hashset; นำเข้า java.util.set; การทดสอบคลาสสาธารณะ { / *** ผู้แต่งเบาลง* หมายเหตุ: สำหรับรายละเอียดโปรดดูเอกสาร Javadoc สำหรับการใช้งานของคำอธิบายประกอบ API* / โมฆะคงที่สาธารณะหลัก (สตริง [] args) โยนข้อยกเว้น {สตริง class_name = "เบา การทดสอบคลาส = class.forName (class_name); วิธี [] วิธี = test.getMethods (); ธงบูลีน = test.isannotationpresent (description.class); if (flag) {คำอธิบาย des = (คำอธิบาย) test.getannotation (description.class); System.out.println ("คำอธิบาย:"+des.value ()); System.out.println ("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Hashset <metht> (); System.out.println ("ชุมชนที่สร้างขึ้น:" name.munity ()); คำอธิบายประกอบ API*/ โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่นข้อยกเว้น {สตริง class_name = "light.javaeye.com.javaeyer"; การทดสอบคลาส = class.forName (class_name); วิธี [] วิธี = test.getMethods (); ธงบูลีน = test.isannotationpresent (description.class); if (flag) {คำอธิบาย des = (คำอธิบาย) test.getannotation (description.class); System.out.println ("คำอธิบาย:"+des.value ()); System.out.println ("-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Boolean OtherFlag = Method [i]. isannotationpresent (name.class); ผลการทำงาน:
คำอธิบาย: Javaeye ผู้ก่อตั้งชุมชนแลกเปลี่ยนซอฟต์แวร์ที่ดีที่สุด: Robbin สร้างชุมชน: Javaeye ผู้ก่อตั้ง: Javaeye สร้างชุมชน: Springside