zoukankan      html  css  js  c++  java
  • java自定义注解

    注解说明

    Java注解又称Java标注,是Java语言5.0版本开始支持加入源代码的特殊语法元数据。为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据。
    Java语言中的类、方法、变量、参数和包等都可以被标注。和Javadoc不同,Java标注可以通过反射获取注解内容。在编译器生成类文件时,注解可以被嵌入到字节码中。Java虚拟机可以保留注解内容,在运行时可以获取到注解内容。

    2|1内置注解

    Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。

    1、作用在代码的注解是

    @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
    @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
    @SuppressWarnings - 指示编译器去忽略注解中声明的警告。
    

    2、作用在其他注解的注解(或者说元注解)是:

    @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
    @Documented - 标记这些注解是否包含在用户文档中。
    @Target - 标记这个注解应该是哪种 Java 成员。
    @Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
    

    3、从 Java 7 开始,额外添加了 3 个注解:

    @SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
    @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
    @Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。
    

    2|2元注解

    1、@Retention

    @Retention annotation指定标记注释的存储方式:

    RetentionPolicy.SOURCE - 标记的注释仅保留在源级别中,并由编译器忽略。
    RetentionPolicy.CLASS - 标记的注释在编译时由编译器保留,但Java虚拟机(JVM)会忽略。
    RetentionPolicy.RUNTIME - 标记的注释由JVM保留,因此运行时环境可以使用它。
    

    2、@Documented

    @Documented 注释表明,无论何时使用指定的注释,都应使用Javadoc工具记录这些元素。(默认情况下,注释不包含在Javadoc中。)有关更多信息,请参阅 Javadoc工具页面。
    

    3、@Target

    @Target 注释标记另一个注释,以限制可以应用注释的Java元素类型。目标注释指定以下元素类型之一作为其值

    ElementType.TYPE 可以应用于类的任何元素。
    ElementType.FIELD 可以应用于字段或属性。
    ElementType.METHOD 可以应用于方法级注释。
    ElementType.PARAMETER 可以应用于方法的参数。
    ElementType.CONSTRUCTOR 可以应用于构造函数。
    ElementType.LOCAL_VARIABLE 可以应用于局部变量。
    ElementType.ANNOTATION_TYPE 可以应用于注释类型。
    ElementType.PACKAGE 可以应用于包声明。
    ElementType.TYPE_PARAMETER
    ElementType.TYPE_USE
    

    4、@Inherited

    @Inherited 注释表明注释类型可以从超类继承。当用户查询注释类型并且该类没有此类型的注释时,将查询类的超类以获取注释类型(默认情况下不是这样)。此注释仅适用于类声明。
    

    5、@Repeatable

    Repeatable Java SE 8中引入的,@Repeatable注释表明标记的注释可以多次应用于相同的声明或类型使用(即可以重复在同一个类、方法、属性等上使用)。
    

    自定义注解:

      使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

    定义注解格式:

      public @interface 注解名 {定义体}

      注解参数的可支持数据类型:

        

    1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
    2.String类型
    3.Class类型
    4.enum类型
    5.Annotation类型
    6.以上所有类型的数组
    

    Annotation类型里面的参数该怎么设定:

      

    第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;   
    第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String;  
    第三,如果只有一个参数成员,最好把参数名称设为"value",后加小括号.例:下面的例子FruitName注解就只有一个参数成员。
    

    注解处理器类库(java.lang.reflect.AnnotatedElement):

    AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的如下四个个方法来访问Annotation信息:
    

      

    注解处理的一个基础:

    方法1:<T extends Annotation> T getAnnotation(Class<T> annotationClass): 返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。
    方法2:Annotation[] getAnnotations():返回该程序元素上存在的所有注解。
    方法3:boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.
    方法4:Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。
    

    实例

    上面的定义解释比较繁琐,下面来看看一段简单的示例代码,相信立马就可以理解了:

    步骤一:定义两个自定义注解,用来修饰属性,一个标注名字,一个标注性别。

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
     
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface Name {//名字自定义注解
     
        public String value() default "";
    }
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
     
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface Sex {//性别自定义注解
     
        public enum GenderType {
            Male("男"),
            Female("女");
            private String genderStr;
            private GenderType(String arg0) {
                this.genderStr = arg0;
            }
            @Override
            public String toString() {
                return genderStr;
            }
        }
        GenderType gender() default GenderType.Male;
    }
    

    步骤二:自定义注解标注在属性上

    public class Person {
     
        @Name(value = "cool_summer_moon")
        public String name;
        public String age;
        @Sex(gender = Sex.GenderType.Male)
        public String sex;
     
        public String getName() { return name; }
        public void setName(String name) {
            this.name = name;
        }
        public String getAge() {
            return age;
        }
        public void setAge(String age) {
            this.age = age;
        }
        public String getSex() {
            return sex;
        }
        public void setSex(String sex) {
            this.sex = sex;
        }
    }
    

    步骤三:定义一个测试工具类,取刚才标注的属性值

    import java.lang.reflect.Field;
     
    public class AnnotionUtils {
     
        public static String getInfo(Class<?> cs){
            String result = "";
            Field[] declaredFields = cs.getDeclaredFields();
            for (Field field : declaredFields){
                if(field.isAnnotationPresent(Name.class)){
                    Name annotation = field.getAnnotation(Name.class);
                    String value = annotation.value();
                    result += (field.getName() + ":" + value + "
    ");
                }
                if(field.isAnnotationPresent(Sex.class)){
                    Sex annotation = field.getAnnotation(Sex.class);
                    String value = annotation.gender().name();
                    result += (field.getName() + ":" + value + "
    ");
                }
            }
            return result;
        }
     
        public static void main(String[] args){
            String info = getInfo(Person.class);
            System.out.println(info);
        }
    }
    

    运行上面程序,结果如下:

    name:cool_summer_moon
    sex:Male
    

    参考:

    https://blog.csdn.net/wangpengzhi19891223/article/details/78131137/
    https://www.cnblogs.com/jajian/p/9695055.html#autoid-3-0-0
    
    
  • 相关阅读:
    python3(二十七)property
    python3(二十六)slots
    python3(二十五) getClassInfo
    python3(二十四) subClas
    python3(二十三)classInstance
    python3(二十二) oop
    python3(二十一) pip
    python3(二十) module
    python3(十九)Partial func
    python3(十八)decorator
  • 原文地址:https://www.cnblogs.com/eternityz/p/12238778.html
Copyright © 2011-2022 走看看