• Java的自定义注解使用实例


    概念

    Java有五个元注解,自动继承java.lang.annotation.Annotation。

    什么是元注解,可以理解为其他普通注解进行解释说明

    @Target  该注解的使用范围,限定应用场景。枚举类 ElemenetType 中

    1. TYPE:类,接口
    2. FIELD:字段,枚举的常量
    3. METHOD:函数(方法)
    4. PARAMETER:参数
    5. CONSTRUCTOR:构造函数
    6. ANNOTATION_TYPE:注解类型
    7. LOCAL_VARIABLE:局部变量
    8. PACKAGE:包

    @Retention  该注解的生存周期,相当于时间戳。枚举类型 RetentionPolicy 中

    1. SOURCE:在源文件中有效,编译后会被丢弃(如@Override,@Deprecated)
    2. CLASS:在class文件中有效,在jvm丢弃
    3. RUNTIME:在运行时有效,class文件保留,jvm运行时保留(很多框架运用反射调用)

    @Documented

    javadoc文档生成工具的使用

    @Inherited

    允许子类继承父类中的注解。

    @Repeatable

    同一种注解可多次使用

    作用

    1. 注释,解释,通过代码的标识元数据生成doc文档;
    2. 使用反射,通过代码标识的元数据对代码进行分析;
    3. 编译检查,通过代码标识的元数据让编译器进行基本检查。

    实例

    定义一个普通的注解,

    public @interface Test
    {
    
    }

    使用我们自定义的注解

    @Test
    public class Person
    {
        @Test
        private String name;
    
        @Test
        private int age;
    
        @Test
        public void say()
        {
            System.out.println("Hello,Java Annotation");
        }
    }

    @Target(ElementType.PACKAGE) 注解作用的目标>包

    这个注解要理解什么是友好声明类和包常量,包中有很多的内部访问的类或常量,就可以统一的放到友好声明类中,这样就方便,而且集中管理,减少friendly类到处游走的情况。

    可以参考这个 https://www.cnblogs.com/DreamDrive/p/5428573.html

    import java.lang.annotation.ElementType;
    @Target(ElementType.PACKAGE)
    public @interface Test
    {
    }
    @Test
    package test;
    
    class Person
    {
    
        private String name;
    
    
        private int age;
    
    
        public void say()
        {
            System.out.println("Hello,Java Annotation");
        }
    }

    @Target(ElementType.CONSTRUCTOR) 注解作用的目标>构造函数

    package test;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Target;
    @Target(ElementType.CONSTRUCTOR)
    public @interface Test
    {
    
    }
    package test;
    
    public class Person
    {
    
        private String name;
    
        private int age;
        @Test
        public Person()
        {
    
        }
    
        public void say()
        {
            System.out.println("Hello,Java Annotation");
        }
    }

    其他范围就不一一列举,都是相同的。

    @Retention(RetentionPolicy.RUNTIME)   生存周期

    代码运行时动态获取注解的信息

    package test;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    @Target(ElementType.CONSTRUCTOR)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Test
    {
    
    }
    package test;
    
    public class Person
    {
    
        private String name;
    
        private int age;
    @Test
    public Person() { } public void say() { System.out.println("Hello,Java Annotation"); } }

     注解的属性-->成员变量

    方法名是成员变量的的名字,变量的类型是他的返回值。

    package test;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME) 
    public @interface Test
    {
        public int age() default 20;
    
        public String name() default "";
    
        public String className();
    }
    package test;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    @Test(age = 15,name = "zhangsan",className = "高三(3)班")
    public class Person
    {
     
        private String name;
    
        private int age;
    
        public Person()
        {
    
        }
    
      
        private void say()
        {
            System.out.println("Hello,Java Annotation");
        }
    }

    既然给了注解,我们要做的工作必然是要提取注解上面的内容,要拿到这些注解就要用到反射。

    package test;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    @Test(age = 15,name = "zhangsan",className = "高三(3)班")
    public class Person
    {private String name;
        
        private int age;
    
        public Person()
        {
    
        }
        
        private void say()
        {
            System.out.println("Hello,Java Annotation");
        }
    
        public static void main(String[] args)
        {
            boolean hasAnnotation = Person.class.isAnnotationPresent(Test.class);
    
            if (hasAnnotation)
            {
                Test test = Person.class.getAnnotation(Test.class);
    
                System.out.println("age:" + test.age());
                System.out.println("name:" + test.name());
                System.out.println("className:" + test.className());
            }
    }
    }

    输出结果

    age:15
    name:zhangsan
    className:高三(3)班

    对于类的属性和方法,都是同样的道理。

    成员注解

    package test;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Field
    {
        public String name();
    }

    函数注解

    package test;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Method
    {
        public String say();
    }

    Person类

    package test;
    
    import java.lang.annotation.Annotation;
    
    @Test(age = 15,name = "zhangsan",className = "高三(3)班")
    public class Person
    {
        @Field(name = "lisi")
        private String name;
    
        private int age;
    
        public Person()
        {
    
        }
        @Method(say = "hello")
        private void say()
        {
            System.out.println("Hello,Java Annotation");
        }
    
        public static void main(String[] args)
        {
            boolean hasAnnotation = Person.class.isAnnotationPresent(Test.class);
    
            if (hasAnnotation)
            {
                Test test = Person.class.getAnnotation(Test.class);
    
                System.out.println("age:" + test.age());
                System.out.println("name:" + test.name());
                System.out.println("className:" + test.className());
            }
    
            try
            {
                java.lang.reflect.Field field = Person.class.getDeclaredField("name");
    
                field.setAccessible(true);
    
                Field check = field.getAnnotation(Field.class);
    
                if (check != null)
                {
                    System.out.println("check value:" + check.name());
                }
    
                java.lang.reflect.Method method = Person.class.getDeclaredMethod("say");  
    
                if (method != null)
                {
                    Annotation[] ans = method.getAnnotations();
                    for (int i = 0; i < ans.length; i++)
                    {
                        System.out.println("method annotation:" + ans[i].annotationType().getSimpleName());
                    }
                 }
    
            } catch (NoSuchFieldException e)
            {
                e.printStackTrace();
            }catch (Exception e){
                e.printStackTrace();
            }
    
        }
    }

    输出

    age:15
    name:zhangsan
    className:高三(3)班
    check value:lisi
    method annotation:Method

    可以看出我们获取了注解上的值,现在都没有实际意义,我们可以用注解来做些什么?

    这些我没办法给出确切答案,只能说根据各人需求去合理利用注解。

    实例

    注解参数赋值

    @Test注解

    package test;
    
    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 Test
    {
        String value();
    }

    Person类属性赋值

    package test;
    
    import org.apache.poi.ss.formula.functions.T;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class Person
    {
        @Test("zhangsan")
        private String name;
    
        @Test("15")
        private int age;
    
        public Person()
        {
    
        }
    
        private void say()
        {
            System.out.println("Hello,Java Annotation");
        }
    
        @Override
        public String toString()
        {
            return "name = " + name + "
    " + "age = " + age;
        }
    
        public static void main(String[] args)
        {
            Person person = new Person();
            try
            {
                //取得成员变量的值
                Field field = Person.class.getDeclaredField("name");
                //打开权限
                field.setAccessible(true);
                //判断属性是否有注解
                if (field.isAnnotationPresent(Test.class))
                {
                    //获取属性上的注解值
                    Test test = field.getAnnotation(Test.class);
                    String name = test.value();
                    //赋值
                    field.set(person,name);
                }
    
                Field field1 = Person.class.getDeclaredField("age");
                field1.setAccessible(true);
                if (field1.isAnnotationPresent(Test.class))
                {
                    Test test = field1.getAnnotation(Test.class);
                    int age = Integer.valueOf(test.value());
                    field1.set(person,age);
                }
                System.out.println(person);
    
            }catch (Exception e)
            {
                e.printStackTrace();
            }
    
        }
    }

    输出

    name = zhangsan
    age = 15

    用注解去检查函数等等。。

    lz不善于用语言表达,所以可能有很多人没看懂,可以看下

    一个大佬讲解的注解说明(简单易懂)

     https://blog.csdn.net/briblue/article/details/73824058

  • 相关阅读:
    Intellij IDEA使用restclient测试
    jmeter测试
    Java中String为什么是不可变的
    为什么String类是不可变的?
    反射中getMethods 与 getDeclaredMethods 的区别
    MD5加密
    将long型转换为多少MB的方法
    ContentProvider往通讯录添加联系人和获取联系人
    安卓软件版本更新
    Servlet生命周期与工作原理
  • 原文地址:https://www.cnblogs.com/dslx/p/10553478.html
Copyright © 2020-2023  润新知