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);

     }

}