1、元註釋和註釋的不同
A、註釋:用於爲代碼提供一個描述性的說明,不會編譯到class文件中,只存在於源文件.java文件中
B、元註釋:是能用運行的代碼,用於修飾類、屬性、方法等java元素,會編譯到class文件中,能被程序讀取
2、元註釋最常見的作用
保存數據,替代xml
XML:
<student id="1" name="張三" age="20"/>
Annotation:
@Student(id=1, name="張三", age=20);
3、元註釋的三個問題
A、定義元註釋
定義名稱,有哪些成員
B、使用元註釋
爲成員賦值
C、讀取元註釋
將成員的值讀取出來
4、定義元註釋
和接口差不多
成員以方法的形式來定義,規則如下:
A、方法必須有返回類型,不能有參數,可以有默認值
B、方法的返回值類型只能是基本類型及數組、String以及數組、枚舉
C、如果元註釋只用一個成員,推薦將成員名定義爲value
就像所有類都繼承自Object一樣,所有的元註釋都繼承自Annotation接口
案例:
/**
* 定義元註釋
* @author Administrator
*/
public @interface Student {
public int id();
public String name();
public int age();
public Sex sex() default Sex.男;
}
5、使用元註釋
元註釋可以修飾類、成員屬性、成員方法、元註釋等
案例:
@Student(age = 18, id = 1, name = "張三")
public class Useage {
@Student(age = 19, id = 2, name = "歷史", sex = Sex.男)
public String field;
@Student(age = 17, id = 3, name = “王五", sex = Sex.男)
public void mthod(){
}
}
6、讀取元註釋
使用反射進行讀取
修飾誰,向誰要
Class、Field、Method共同的方法:
A、isAnnotationPresent(Student.class)
判斷Java元素是否被元註釋Student修飾
B、getAnnotation(Student.class)
獲取指定的元註釋
案例:
/**
* 使用元註釋
* @author Administrator
*/
@Student(age = 18, id = 1, name = "張三")
public class Useage {
@Student(age = 19, id = 2, name = "李四", sex = Sex.男)
public String field;
@Student(age = 17, id = 3, name = "王五", sex = Sex.男)
public void method(){
Class c;
}
public static void main(String[] args) throws Exception{
Useage u = new Useage();
Class c = u.getClass();
if(c.isAnnotationPresent(Student.class)){
Student stu = (Student)
c.getAnnotation(Student.class);
System.out.println(stu.id());
System.out.println(stu.name());
System.out.println(stu.age());
System.out.println(stu.sex());
}
Field field = c.getDeclaredField("field");
if(field.isAnnotationPresent(Student.class)){
Student stu = field.getAnnotation(Student.class);
System.out.println(stu.id());
System.out.println(stu.name());
System.out.println(stu.age());
System.out.println(stu.sex());
}
Method method = c.getDeclaredMethod("method");
if(method.isAnnotationPresent(Student.class)){
Student stu = method.getAnnotation(Student.class);
System.out.println(stu.id());
System.out.println(stu.name());
System.out.println(stu.age());
System.out.println(stu.sex());
}
}
}
7、元註釋的元註釋
A、@Target 用於指定元註釋可以修飾哪些Java元素
只有唯一的一個成員value,類型是ElementType枚舉數組
可能的值有:
public enum ElementType {
TYPE,
FIELD,
METHOD,
PARAMETER,
CONSTRUCTOR,
LOCAL_VARIABLE,
ANNOTATION_TYPE,
PACKAGE
}
例如:@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})表示可以修飾類、屬性、方法
8、@Retention 決定元註釋的值是否能通過反射讀取
SOURCE:編譯後被丟棄
CLASS:編譯後元註釋的信息會保留在class文件中,但是運行時無法讀取
RUNTIME:編譯後元註釋的信息會保留在class文件中,並且能實時讀取
9、寫一個輸出對象信息的工具,能自定義屬性名和日期格式
A、定義元註釋
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Name {
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Format {
String value();
}
B、定義工具類Values
public class Values {
/**
* 打印對象obj中的所有屬性值
* @param obj
*/
public static void prints(Object obj) throws Exception{
Class c = obj.getClass();
//獲取類中所有的屬性
Field[] fields = c.getDeclaredFields();
//循環遍歷,打印出所有的屬性值
if(fields != null){
for(Field field : fields){
field.setAccessible(true);//開放權限
String name = null;
//field是否被Name修飾
if(field.isAnnotationPresent(Name.class)){
//讀取@Name中的value值
name = field.getAnnotation(Name.class).value();
}else{
//否則就輸出屬性名
name = field.getName();
}
String value = null;
if(field.isAnnotationPresent(Format.class)){
String pattern = field.getAnnotation(Format.class).value();
DateFormat df = new SimpleDateFormat(pattern);
value = df.format(field.get(obj));
}else{
value = field.get(obj).toString();
}
System.out.println(name + "=" + value);
}
}
}
}
C、定義測試用的Java實體類
/**
* 產品
* @author Administrator
*/
public class Product {
@Name("產品編號")
private int pid;
@Name("名稱")
private String name;
private double price;
@Name("生產日期")
@Format("yyyy年MM月dd日")
private Date date;
public Product() {
// TODO Auto-generated constructor stub
}
public Product(int pid, String name, double price, Date date) {
super();
this.pid = pid;
this.name = name;
this.price = price;
this.date = date;
}
}
public class Employee {
private int eid;
private String name;
@Name("愛好")
private String hobby;
@Format("yyyy/MM/dd HH:mm:ss")
@Name("生日")
private Date birthday;
public Employee() {
// TODO Auto-generated constructor stub
}
public Employee(int eid, String name, String hobby, Date birthday) {
super();
this.eid = eid;
this.name = name;
this.hobby = hobby;
this.birthday = birthday;
}
}
D、測試
public class Test {
public static void main(String[] args) throws Exception {
Product p = new Product(1, "手機", 3000, new Date());
Values.prints(p);
Employee e = new Employee(1, “王二", "編程",
java.sql.Date.valueOf("1996-9-9"));
Values.prints(e);
}
}