"ตอนนี้มาสร้างและใช้คำอธิบายประกอบสองสามรายการ"

"ตัวอย่างเช่น สมมติว่าเรากำลังเขียนเอนจิ้นเกม เกมของเรามีตัวละครมากมายที่แบ่งออกเป็น 3 ประเภท ได้แก่ เอลฟ์ องครักษ์ในวัง และวายร้าย"

"ขณะที่เกมกำลังพัฒนา อาจมีการเพิ่มตัวละครใหม่ ซึ่งจะทำให้ความสมดุลของเกมเปลี่ยนไป ดังนั้น มันจะสะดวกมากที่จะกำหนด 'คลาสตัวละคร' แต่ละคลาสของตัวเองเพื่ออธิบายลักษณะทางกายภาพของมัน"

"การทำเช่นนี้จะทำให้ง่ายต่อการจำลองการต่อสู้ระหว่างตัวละครต่างๆ และ/หรือคำนวณความสมดุลของเกมได้อย่างรวดเร็ว"

"ฉันเห็นด้วย นั่นเป็นความคิดที่ดี"

"มาสร้าง คำอธิบายประกอบ @Personที่จะเก็บพลังชีวิต ความแข็งแกร่ง และเวทมนตร์ ตลอดจนพารามิเตอร์การโจมตีและการป้องกัน นี่คือลักษณะของคำอธิบายประกอบ:"

ตัวอย่าง
@interface Person
{
 String name() default "";
 int live();
 int strength();
 int magic() default 0;
 int attack() default 0;
 int defense();
}

"และตัวอย่าง ต่อไปนี้เป็นคำอธิบายของ Forest Elf Mage:"

ตัวอย่าง
@Person(live = 100, strength = 10, magic = 5, attack = 20, defense = 20)
class Elf
{}

"และนี่คือลักษณะของคำอธิบายของตัวร้ายหลัก:"

ตัวอย่าง
@Person(live = 1000, strength = 150, magic = 250, attack = 99, defense = 99)
class EvilMaster
{}

"ฉันเข้าใจแล้ว มันทำให้ฉันนึกถึงส่วนต่อประสานเครื่องหมาย"

"ใช่ ยกเว้น อย่างแรก คุณไม่จำเป็นต้องสืบทอดสิ่งใดๆ และอย่างที่สอง คุณสามารถเก็บข้อมูลเพิ่มเติมในคำอธิบายประกอบได้"

"มีคำอธิบายประกอบอีกสองสามรายการที่ใช้ทำเครื่องหมายคำอธิบายประกอบ นี่คือ: "

"คำอธิบายประกอบ @Retention บ่งชี้ตำแหน่งที่คำอธิบายประกอบของเราจะปรากฏให้เห็น: เฉพาะในซอร์สโค้ด แม้หลังจากการคอมไพล์ หรือแม้แต่ในขณะรันไทม์"

"คำอธิบายประกอบ @Target ระบุสิ่งที่สามารถทำเครื่องหมายได้โดยใช้คำอธิบายประกอบ: คลาส ฟิลด์ เมธอด พารามิเตอร์เมธอด ฯลฯ"

"ถ้าเราต้องการให้คำอธิบายประกอบของเรามีผลกับคลาสที่สืบทอดคลาสที่มีคำอธิบายประกอบ ไม่ใช่เฉพาะกับคลาสที่มีคำอธิบายประกอบเท่านั้น เราจำเป็นต้องใส่คำอธิบายประกอบด้วย @Inherited"

"นี่คือ ลักษณะของคำอธิบายประกอบ @Person ของเรา "

ตัวอย่าง
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
@interface Person
{
 String name() default "";
 int live();
 int strength();
 int magic() default 0;
 int attack() default 0;
 int defence();
}

"น่าสนใจมาก ขอบคุณ ริชิ"

แต่คุณจะทำงานกับคำอธิบายประกอบเหล่านี้ในโปรแกรมได้อย่างไร คุณใช้มันอย่างไร? คุณอ่านค่าของมันได้อย่างไร”

"โดยทั่วไปจะทำโดยใช้การสะท้อน "

"นี่คือวิธีที่เราจะตัดสินว่าตัวละครใดแข็งแกร่งกว่า:"

ตัวอย่าง
public boolean fight(Class first, Class second)
{
 if (!first.isAnnotationPresent(Person.class))
  throw new RuntimeException("first param is not game person");
 if (!second.isAnnotationPresent(Person.class))
  throw new RuntimeException("second param is not game person");

 Person firstPerson = (Person) first.getAnnotation(Person.class);
 Person secondPerson = (Person) second.getAnnotation(Person.class);

 int firstAttack = firstPerson.attack() * firstPerson.strength() + firstPerson.magic();
 int firstPower = firstPerson.live() * firstPerson.defence() * firstAttack;

 int secondAttack = secondPerson.attack() * secondPerson.strength() + secondPerson.magic();
 int secondPower = secondPerson.live() * secondPerson.defence() * secondAttack;

 return firstPower > secondPower;
}

"นี่คือวิธีการที่เราต้องการ:"

วิธีการ คำอธิบาย
isAnnotationPresent(Annotation.class)
ตรวจสอบว่าคลาสมีคำอธิบายประกอบที่ระบุหรือไม่
getAnnotation(Annotation.class)
ส่งกลับอ็อบเจกต์คำอธิบายประกอบหากคลาสมีคำอธิบายประกอบที่ระบุ
Annotation[] getAnnotations()
ส่งกลับอาร์เรย์ของคำอธิบายประกอบของคลาสทั้งหมด

"เยี่ยมมาก ฉันไม่คาดหวังว่าการได้รับคำอธิบายประกอบจะง่ายขนาดนี้"

"เอ่อ-ฮะ" เพียงเรียกเมธอด getAnnotation ของออบเจกต์ แล้วส่งประเภทคำอธิบายประกอบที่ต้องการ"

"ก็วันนี้แหละ"

"ขอบคุณ Rishi นี่เป็นบทเรียนที่น่าสนใจมาก ตอนนี้ฉันไม่กลัวคำอธิบายประกอบเหมือนฉันดื่มน้ำ"