go to http://oracle.in.th

Friday, October 2, 2009

Annotation Part#2

Class Annotation

เราจะมาดูตัวอย่างการใช้กันใน class A
// A.java Class Annotation

import mytag.Author;
import mytag.Version;

@Author( name = "John Rambo" )
@Version( major = 1, minor = 1 )

public class A { }

ซึ่งการประกาศ annotation นั้นจะไปประกาศหน้า class เพื่อบอกว่าใครคือผู้สร้าง class นี้และเป็น version อะไร สังเกตว่า annotation จะประกาศกี่อันก็ได้ จากนั้นเราจะมาดูวิธีเรียกใช้ annotation กันว่า ว่ามีวิธีเรียกยังไงใน class ATest

โดยก่อนที่เราจะเรียกใช้เราลอง compile file A.java ดูก่อน โดยเปิด cmd ขึ้นมาแล้วไปยัง directory anno ดังตัวอย่างรูปด้านล่าง

directory anno

ให้ compile class ใน package mytag ทั้งหมดก่อนโดยใช้คำสั่งดังนี้
javac mytag\*.java

จากนั้นลอง compile A.java โดยคำสั่ง
javac A.java

จากนั้นเราลองดูขนาด file A.class กันว่ามีขนาดเท่าไรโดยใช้คำสั่ง
dir A.class

จะพบว่ามันมีขนาดมาถึง 311 byte ถือว่าเยอะมากสำหรับ class ธรรมดาโดยปกติจะประมาณ 100 กว่า byte ทดสอบได้โดย comment annotation ใน A.java ออกแล้วลอง compile ใหม่ดูจะพบว่าเนื้อที่ของ A.class จะเหลือเพียง 176 byte เท่านั้น ที่เป็นเช่นนี้เพราะมันจะเก็บ element ของ annotation เหล่านี้ไว้ใน A.class

ต่อมาลองเรียกใช้ annotation กันซึ่ง class แรกที่เราจะลองนั้นคือ ATest.java
// ATest.java
import mytag.Author;
import mytag.Version;

class ATest {
public static void main(String args[]) {
Author a = A.class.getAnnotation(Author.class);
System.out.println("Author: " + a.name());
Version v = A.class.getAnnotation(Version.class);
System.out.println("Version: " + v.major() + "." + v.minor());
}
}

การจะเอา annotation ที่ติดอยู่ใน class ออกมา เราจะเรียกใช้ property class ซึ่งติดอยู่ใน class ทุก class ที่เราสร้างขึ้นมา โดย property class จะไปอ้างถึง file A.class ที่เราได้มาจากการ compile A.java จากนั้นเราใช้ method getAnnotation(Author.class) โดยตอน get นั้นต้องใส่ property class ของ annotation ที่เราต้องการจะอ่านด้วยจากนั้นเมื่อได้ annotation แล้วเราจึง get ค่าต่างๆออกมากตามที่เรากำหนดไว้ใน element ( การที่เราสามารถดึงค่า annotation ที่อยู่ใน class ออกมาได้นั้นเป็นเพราะ เราใช้ Refection API เข้ามาช่วย ในตัวอย่างนี้เป็นเพียงแค่ เศษเสี้ยวของความสามารถของ Reflection API เท่านั้น สามารถศึกษาต่อได้ ที่นี่ )
System.out.println("Author: " + a.name());
System.out.println("Version: " + v.major() + "." + v.minor());


Class Member Annotation

จากที่เราลองประกาศ annotation บน class แล้ว เราลองประกาศ annotation บน attribute และ method ดูบ้าง ลองไปดูใน code BTest.java ดู ในนั้นจะมี class B อยู่ โดย class B ใน BTest.java จะมีการประกาศ annotation บน attribute และ method ดัง code ด้านล่าง เพื่อเป็นตัวบอกว่า attribute หรือ method เหล่านี้ใครเป็นผู้สร้าง
// part of BTest.java
class B {
@Author( name = "John Rambo" )
public int x;
@Author( name = "Jack Ripper" )
public static void f() { }
}

จากนั้นเราลองดึงเอา annotation ออกมาใช้ โดยวิธีการดึงและการเรียกออกมา จะมีวิธีการเรียกที่แตกต่างกับวิธีของ Class Annotation ดัง code ด้านล่าง
// part of BTest.java
public static void main(String args[])
throws NoSuchMethodException, NoSuchFieldException {
Field f = B.class.getField("x");
Author fanno = f.getAnnotation(Author.class);
System.out.println(fanno.name());

Method m = B.class.getMethod("f");
Author manno = m.getAnnotation(Author.class);
System.out.println(manno.name());
}

ถ้าลองสังเกตจากตัวอย่างที่แล้ว การดึง annotation ในประเภท Class Annotation เราสามารถดึงออกมาเป็น Object ของ annotation นั้นได้โดยตรงๆ แต่การดึง annotation ในประเภท Class Member Annotation นั้นไม่ใช่ การจะดึงออกมาต้องดึงออกมาเป็น object ของ java.lang.reflect.Field ถ้าหากเราจะดึง annotation ของ attribute แต่ถ้าเป็นการดึง annotation ของ method เราต้องดึงออกมาเป็น object ของ java.lang.reflect.Method
Field f = B.class.getField("x");
Method m = B.class.getMethod("f");

โดยการเรียก object ของ java.lang.reflect.Field และ java.lang.reflect.Method นั้น เราจะเรียกผ่าน method getField() และ getMethod() ตามลำดับโดยต้องระบุชื่อของ attribute หรือ method ที่ต้องการเรียก annotation ของ attribute หรือ method นั้นๆ จากนั้นเราจึงเอา object ของ java.lang.reflect.Field และ java.lang.reflect.Method นั้นมาดึงเอา annotation ออกมาอีกที
Author fanno = f.getAnnotation(Author.class);
Author manno = m.getAnnotation(Author.class);

ซึ่งจากทั้งสองตัวอย่างคงจะเข้าใจ annotation มากขึ้น ซึ่งเราจะมาเล่นของลูกเล่นใน annotation กันต่อ

คราวหน้า เราจะมาต่อกันด้วย Default Value นะครับ

Reference from : dr. Werasak Suengtaworn

Compose by : @plaumkamon
ข้อเขียนนี้ช่วยฉัน:  

1 comment:

Tom Condo said...

ภาค 2 มาแล้ว ว้าวๆๆ

Post a Comment