zoukankan      html  css  js  c++  java
  • Java Annontation 注解的学习和理解

    /**
     * <html>
     * <body>
     *  <P> Copyright 1994 JsonInternational</p>
     *  <p> All rights reserved.</p>
     *  <p> Created by Jason</p>
     *  </body>
     * </html>
     */
    package cn.ucaner.core.annotation;
    
    /**
    Annontation是Java5开始引入的新特征,中文名称叫注解。
    它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。
    为程序的元素(类、方法、成员变量)加上更直观更明了的说明,这些说明信息是与程序的业务逻辑无关,并且供指定的工具或框架使用。
    Annontation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。
     
    Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。
    注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。
    包含在 java.lang.annotation 包中。
    
    常见的用法 :
          1、生成文档。这是最常见的,也是java 最早提供的注解。常用的有@param @return 等
          2、跟踪代码依赖性,实现替代配置文件功能。比如Dagger 2依赖注入,未来java开发,将大量注解配置,具有很大用处;
          3、在编译时进行格式检查。如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。
          
    注解的原理:
        注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。
        而我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象$Proxy1。
        通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler的invoke方法。
        该方法会从memberValues这个Map中索引出对应的值。
        而memberValues的来源是Java常量池。
    
    元注解:
       @Documented –注解是否将包含在JavaDoc中
       @Retention –什么时候使用该注解
       @Target –注解用于什么地方
       @Inherited – 是否允许子类继承该注解
       
    1.)@Retention– 定义该注解的生命周期
      ●   RetentionPolicy.SOURCE : 在编译阶段丢弃。
               这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。
            @Override, @SuppressWarnings都属于这类注解。
            
      ●   RetentionPolicy.CLASS : 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式
      
      ●   RetentionPolicy.RUNTIME : 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
    
    2.)@Target – 表示该注解用于什么地方。默认值为任何元素,表示该注解用于什么地方。可用的ElementType参数包括
      ● ElementType.CONSTRUCTOR:用于描述构造器
      ● ElementType.FIELD:成员变量、对象、属性(包括enum实例)
      ● ElementType.LOCAL_VARIABLE:用于描述局部变量
      ● ElementType.METHOD:用于描述方法
      ● ElementType.PACKAGE:用于描述包
      ● ElementType.PARAMETER:用于描述参数
      ● ElementType.TYPE:用于描述类、接口(包括注解类型) 或enum声明
    
    3.)@Documented–一个简单的Annotations标记注解,表示是否将注解信息添加在java文档中。
    
    4.)@Inherited – 定义该注释和子类的关系
            @Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。
             如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
    */
    public class AnnoDefined {
    
    }
    /**
     * <html>
     * <body>
     *  <P> Copyright 1994 JsonInternational</p>
     *  <p> All rights reserved.</p>
     *  <p> Created on 19941115</p>
     *  <p> Created by Jason</p>
     *  </body>
     * </html>
     */
    package cn.ucaner.core.annotation;
    
    public class AnnoDemo {
        
        @FieldMeta(id=true,name="序列号",order=1,description="ID")  
        private int id;  
        
        @FieldMeta(name="姓名",order=3,description="姓名")  
        private String name;  
        
        @FieldMeta(name="年龄",order=2)  
        private int age;  
        
        @FieldMeta(description="描述",order=4)  
        public String desc(){  
            return "java反射获取annotation的测试";  
        }  
        
        public int getId() {  
            return id;  
        }  
        public void setId(int id) {  
            this.id = id;  
        }  
        public String getName() {  
            return name;  
        }  
        public void setName(String name) {  
            this.name = name;  
        }  
        public int getAge() {  
            return age;  
        }  
        public void setAge(int age) {  
            this.age = age;  
        }  
    
    }
    /**
     * <html>
     * <body>
     *  <P> Copyright 1994 JsonInternational</p>
     *  <p> All rights reserved.</p>
     *  <p> Created by Jason</p>
     *  </body>
     * </html>
     */
    package cn.ucaner.core.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
    * @Package:cn.ucaner.core.annotation   
    * @ClassName:FieldMeta   
    * @Description:   <p> @FieldMeta  - 注解描述信息 </p>
    * @Author: - Jason   
    * @CreatTime:2018年10月18日 下午9:53:45   
    * @Modify By:   
    * @ModifyTime:  2018年10月18日
    * @Modify marker:   
    * @version    V1.0
     */
    @Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到  
    @Target({ElementType.FIELD,ElementType.METHOD})//定义注解的作用目标**作用范围字段、枚举的常量/方法  
    @Documented//说明该注解将被包含在javadoc中  
    public @interface FieldMeta {
        
        /** 
         * 是否为序列号 
         * @return 
         */  
        boolean id() default false; 
        
        /** 
         * 字段名称 
         * @return 
         */  
        String name() default "default_name";  
        
        /** 
         * 是否可编辑 
         * @return 
         */  
        boolean editable() default true;  
        
        /** 
         * 是否在列表中显示 
         * @return 
         */  
        boolean summary() default true;  
        
        /** 
         * 字段描述 
         * @return 
         */  
        String description() default ""; 
        
        /** 
         * 排序字段 
         * @return 
         */  
        int order() default 0;  
    
    }
    /**
     * <html>
     * <body>
     *  <P> Copyright 1994 JsonInternational</p>
     *  <p> All rights reserved.</p>
     *  <p> Created on 19941115</p>
     *  <p> Created by Jason</p>
     *  </body>
     * </html>
     */
    package cn.ucaner.core.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /*1.CONSTRUCTOR:用于描述构造器
    2.FIELD:用于描述域
    3.LOCAL_VARIABLE:用于描述局部变量
    4.METHOD:用于描述方法
    5.PACKAGE:用于描述包
    6.PARAMETER:用于描述参数
    7.TYPE:用于描述类、接口(包括注解类型) 或enum声明*/
    
    /*(RetentionPoicy)
    1.SOURCE:在源文件中有效(即源文件保留)
    2.CLASS:在class文件中有效(即class保留)
    3.RUNTIME:在运行时有效(即运行时保留)*/
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface FruitName {
        
        String value() default "Apple";
    }
    /**
     * <html>
     * <body>
     *  <P> Copyright 1994 JsonInternational</p>
     *  <p> All rights reserved.</p>
     *  <p> Created by Jason</p>
     *  </body>
     * </html>
     */
    package cn.ucaner.core.annotation;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    
    
    /**
    * @Package:cn.ucaner.core.annotation   
    * @ClassName:Parent   
    * @Description:   <p> Parent<T> </p>
    * @Author: - Jason   
    * @CreatTime:2018年10月18日 下午9:54:26   
    * @Modify By:   
    * @ModifyTime:  2018年10月18日
    * @Modify marker:   
    * @version    V1.0
     */
    public class Parent<T> {
        
        private Class<T> entity;  
          
        public Parent() {  
            init();  
        }  
      
        public List<SortableField> init(){  
            List<SortableField> list = new ArrayList<SortableField>();  
            /**getClass().getGenericSuperclass()返回表示此 Class 所表示的实体(类、接口、基本类型或 void) 
             * 的直接超类的 Type(Class<T>泛型中的类型),然后将其转换ParameterizedType。。 
             *  getActualTypeArguments()返回表示此类型实际类型参数的 Type 对象的数组。 
             *  [0]就是这个数组中第一个了。。 
             *  简而言之就是获得超类的泛型参数的实际类型。。*/  
           // entity = (Class<T>)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];  
    //      FieldMeta filed = entity.getAnnotation(FieldMeta.class);  
            this.getClass().getGenericSuperclass();
            //genericSuperclass.
            if(this.entity!=null){  
                  
                /**返回类中所有字段,包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段 
                 * entity.getFields();只返回对象所表示的类或接口的所有可访问公共字段 
                 * 在class中getDeclared**()方法返回的都是所有访问权限的字段、方法等; 
                 * 可看API 
                 * */  
                Field[] fields = entity.getDeclaredFields();  
    //            
                for(Field f : fields){  
                    //获取字段中包含fieldMeta的注解  
                    FieldMeta meta = f.getAnnotation(FieldMeta.class);  
                    if(meta!=null){  
                        SortableField sf = new SortableField(meta, f);  
                        list.add(sf);  
                    }  
                }  
                  
                //返回对象所表示的类或接口的所有可访问公共方法  
                Method[] methods = entity.getMethods();  
                  
                for(Method m:methods){  
                    FieldMeta meta = m.getAnnotation(FieldMeta.class);  
                    if(meta!=null){  
                        SortableField sf = new SortableField(meta,m.getName(),m.getReturnType());  
                        list.add(sf);  
                    }  
                }  
                //这种方法是新建FieldSortCom类实现Comparator接口,来重写compare方法实现排序  
    //          Collections.sort(list, new FieldSortCom());  
                Collections.sort(list, new Comparator<SortableField>() {  
                    @Override  
                    public int compare(SortableField s1,SortableField s2) {  
                        return s1.getMeta().order()-s2.getMeta().order();  
    //                  return s1.getName().compareTo(s2.getName());//也可以用compare来比较  
                    }  
                      
                });  
            }  
            return list;  
              
        }  
    
    }
    /**
     * <html>
     * <body>
     *  <P> Copyright 1994 JsonInternational</p>
     *  <p> All rights reserved.</p>
     *  <p> Created on 19941115</p>
     *  <p> Created by Jason</p>
     *  </body>
     * </html>
     */
    package cn.ucaner.core.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
    * @Package:cn.ucaner.core.annotation   
    * @ClassName:SayHiAnnotation   
    * @Description:   <p> 自定义注解,用来配置方法</p>
    * @Author: - Jason   
    * @CreatTime:2018年4月10日 下午9:39:10   
    * @Modify By:   
    * @ModifyTime:  2018年4月10日
    * @Modify marker:   
    * @version    V1.0
     */
    @Retention(RetentionPolicy.RUNTIME) // 表示注解在运行时依然存在
    @Target(ElementType.METHOD) // 表示注解可以被使用于方法上
    public @interface SayHiAnnotation {
        
         String paramValue() default "Jason"; 
        // 表示我的注解需要一个参数 名为"paramValue" 默认值为"Jason"
    }
    /**
     * <html>
     * <body>
     *  <P> Copyright 1994 JsonInternational</p>
     *  <p> All rights reserved.</p>
     *  <p> Created on 19941115</p>
     *  <p> Created by Jason</p>
     *  </body>
     * </html>
     */
    package cn.ucaner.core.annotation;
    
    /**
    * @Package:cn.ucaner.core.annotation   
    * @ClassName:SayHiEmlement   
    * @Description:   <p> 要使用SayHiAnnotation的元素所在类 </br> 由于我们定义了只有方法才能使用我们的注解,我们就使用多个方法来进行测试</p>
    * @Author: - DaoDou   
    * @CreatTime:2018年4月10日 下午9:39:49   
    * @Modify By:   
    * @ModifyTime:  2018年4月10日
    * @Modify marker:   
    * @version    V1.0
     */
    public class SayHiEmlement {
    
        // 普通的方法
        public void SayHiDefault(String name,String age){
            System.out.println("Hi, " + name+age);
        }
        
        // 使用注解并传入参数的方法
        @SayHiAnnotation(paramValue="Jack")
        public void SayHiAnnotation(String name,String age){
            System.out.println("Hi, " + name+age);
        }
        
        // 使用注解并使用默认参数的方法
        @SayHiAnnotation
        public void SayHiAnnotationDefault(String name,String age){
            System.out.println("Hi, " + name + age);
        }
    }
    /**
     * <html>
     * <body>
     *  <P> Copyright 1994 JsonInternational</p>
     *  <p> All rights reserved.</p>
     *  <p> Created by Jason</p>
     *  </body>
     * </html>
     */
    package cn.ucaner.core.annotation;
    
    import java.lang.reflect.Field;
    
    /**
    * @Package:cn.ucaner.core.annotation   
    * @ClassName:SortableField   
    * @Description:   <p> SortableField 可排序字段 </p>
    * @Author: - Jason   
    * @CreatTime:2018年10月18日 下午9:55:25   
    * @Modify By:   
    * @ModifyTime:  2018年10月18日
    * @Modify marker:   
    * @version    V1.0
     */
    public class SortableField {
        
        public SortableField(){}  
         
        public SortableField(FieldMeta meta, Field field) {  
            super();  
            this.meta = meta;  
            this.field = field;  
            this.name=field.getName();  
            this.type=field.getType();  
        }  
          
          
        public SortableField(FieldMeta meta, String name, Class<?> type) {  
            super();  
            this.meta = meta;  
            this.name = name;  
            this.type = type;  
        }  
      
      
        private FieldMeta meta;  
        private Field field;  
        private String name;  
        private Class<?> type;  
          
        public FieldMeta getMeta() {  
            return meta;  
        }  
        public void setMeta(FieldMeta meta) {  
            this.meta = meta;  
        }  
        public Field getField() {  
            return field;  
        }  
        public void setField(Field field) {  
            this.field = field;  
        }  
        public String getName() {  
            return name;  
        }  
        public void setName(String name) {  
            this.name = name;  
        }  
      
        public Class<?> getType() {  
            return type;  
        }  
      
        public void setType(Class<?> type) {  
            this.type = type;  
        }  
    
    }
    /**
     * <html>
     * <body>
     *  <P> Copyright 1994 JsonInternational</p>
     *  <p> All rights reserved.</p>
     *  <p> Created by Jason</p>
     *  </body>
     * </html>
     */
    package cn.ucaner.core.annotation;
    
    import java.lang.reflect.Field;
    
    /**
    * @Package:cn.ucaner.core.annotation   
    * @ClassName:TestMain   
    * @Description:   <p> TestMain </p>
    * @Author: - Jason   
    * @CreatTime:2018年10月19日 下午3:17:20   
    * @Modify By:   
    * @ModifyTime:  2018年10月19日
    * @Modify marker:   
    * @version    V1.0
     */
    public class TestMain {
    
        @FieldMeta(name="Jason")//注解的使用
        private Object obj;
        
        @FieldMeta(name="Andy",description="Intersting")
        private String name;
        
        @FruitName(value="Apple")
        @FieldMeta
        private String profile;
        
        public String getProfile() {
            return profile;
        }
    
        public void setProfile(String profile) {
            this.profile = profile;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    
        public Object getObj() {
            return obj;
        }
    
        public void setObj(Object obj) {
            this.obj = obj;
        }
    
    
        /**
         * @Description: Just for test   注解反射的方式拿到元信息数据
         * @throws Exception void
         */
        public static void main(String[] args) throws Exception{
            
             Field[] fields = TestMain.class.getDeclaredFields();
             for (Field field : fields) {
                System.out.println(field.getName());
                 if(field.isAnnotationPresent(FieldMeta.class)){
                     FieldMeta fieldMeta = field.getAnnotation(FieldMeta.class);
                     String str = fieldMeta.name();
                     String description = fieldMeta.description();
                     System.out.println(str);
                     System.out.println(description);
                  }if (field.isAnnotationPresent(FruitName.class)) {
                      FruitName fruitName = field.getAnnotation(FruitName.class);
                      System.out.println(fruitName.value());
                }else{
                      //FruitName fruitName = field.getAnnotation(FruitName.class);
                      //System.out.println(fruitName.value());
                  }
             }
             
          }
    
    }
    //Output
    //obj
    //Jason
    //
    //name
    //Andy
    //Intersting
    //profile
    //default_name
    //
    //Apple
  • 相关阅读:
    c++ stringstream
    c语言中字符串数组初始化的一点总结&& c++访问控制的三种方式
    Leetcode 2. Add Two Numbers(medium)
    面试题---反转一个字符串
    编程题---在数组中取一个位置,让这个位置之前的数的和与之后的和的差绝对值最小
    美团面试准备
    Leetcode 101. Symmetric Tree(easy)
    Leetcode 665. Non-decreasing Array(Easy)
    617. Merge Two Binary Trees(Easy)
    423. Reconstruct Original Digits from English(Medium)
  • 原文地址:https://www.cnblogs.com/jasonandy/p/9821195.html
Copyright © 2011-2022 走看看