zoukankan      html  css  js  c++  java
  • java 注解使用笔记

    一、语法

    注解也属于一种类型

    public @interface MyTestAnnotation {
    }

    用@interface描述

    根据情况可以应用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。

    @MyTestAnnotation
    public class MyTestClass {
    }

    二、元注解

    用于修饰注解,就是注解的注解,元注解是一种基本注解。

    目前元注解有@Retention、@Documented、@Target、@Inherited、@Repeatable五种。

    1.@Retention 定义注解的生命周期

          RetentionPolicy.SOURCE : 注解只在源码阶段保留,在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。例如:@Override, @SuppressWarnings这类注解。
         RetentionPolicy.CLASS : 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中, 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。
         RetentionPolicy.RUNTIME : 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取,始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。自定义的注解通常使用这种方式。

    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyTestAnnotation {

    }


    2.@Target 当一个注解被 @Target 注解时,这个注解就被限定了运用的场景。表示该注解用于什么地方,比如类、接口、方法等。默认值为任何元素,表示该注解用于什么地方。

    可用的ElementType参数包括:

    ElementType.ANNOTATION_TYPE 可以给一个注解进行注解

    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的子类。

    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    public @interface MyTestAnnotation {
    }
    @MyTestAnnotation
    public class MyTestClass {
    }
    public class MySubTestClass extends MyTestClass {
    }

    MySubTestClass类继承其父类的注解


    5.@Repeatable - 指定该注解可重复使用

        使用@Repeatable修饰表示该注解可以为重复使用。@Repeatable是 Java 1.8 才加进来的。

    @interface Persons {
        Person[]  value();
    }


    @Repeatable(Persons.class)
    @interface Person{
        String role default "";
    }


    @Person(role="worker")
    @Person(role="coder")
    @Person(role="husband")
    public class Tom{

    }

    三、注解的属性

    注解的属性也叫做成员变量。注解只有成员变量,没有方法。注解的成员变量在注解的定义中以无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。

    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Target(ElementType.TYPE)
    public @interface MyTestAnnotation {
        public int id() default -1;
        public String name() default "hello world";
    }

    上述代码定义了id和name两个属性,并且定义了缺省值。

    在使用的时候,我们应该给它们进行赋值。

    赋值的方式是在注解的括号内以 value=”” 形式,多个属性之前用 ,隔开,如果不赋值,则私用缺省。

    @MyTestAnnotation(id = 1000,name = "I love this game")
    public class MyTest2Class {
    }

    需要注意的是,在注解中定义属性时它的类型必须是 8 种基本数据类型外加 类、接口、注解及它们的数组。

    注解中属性可以有默认值,默认值需要用 default 关键值指定。

    因为有默认值,所以无需要再在 @ MyTestAnnotation后面的括号里面进行赋值了,这一步可以省略。

    @MyTestAnnotation
    public class MyTestClass {
    }

    还有一种情况,

    如果一个注解内仅仅只有一个名字为 value 的属性时(属性必须是value这个字),应用这个注解时可以直接接属性值填写到括号内。

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface CheckNum {
        String value();
    }

    @MyTestAnnotation
    public class MyTestClass {
        @CheckNum("true")
        private int myflag;
    }

    最后,还需要注意的一种情况是一个注解没有任何属性。比如

    @Retention(RetentionPolicy.RUNTIME)
    public @interface CheckString {
    }

    那么在应用这个注解的时候,括号都可以省略。

    @MyTestAnnotation
    public class MyTestClass {
        @CheckNum("true")
        private int myflag;

        @CheckString
        private String myStr;
    }

    四、获取注解

    注解给类或者方法等打上标签,最终是程序在编译或运行时读取做出相应的动作。

    获取注解本质上是采用反射。

    1.定义注解

    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Target(ElementType.TYPE)
    public @interface MyTestAnnotation {
        public int id() default -1;
        public String name() default "hello world";
    }
     

    @Retention(RetentionPolicy.RUNTIME)
    public @interface CheckNum {
        String value();
    }

     

    @Retention(RetentionPolicy.RUNTIME)
    public @interface CheckString {
    }

     

    2.给类加注解

    @MyTestAnnotation
    public class MyTestClass {
        @CheckNum("true")
        private int myflag;

        @CheckString
        @CheckNum("false")
        private String checkMyStr(String str)
        {
            return "";
        }

    }

    @MyTestAnnotation(id = 1000,name = "I love this game")
    public class MyTest2Class {
    }
    public class MySubTestClass extends MyTestClass {
    }

    3.获取注解

    private static void testAnnotation() throws Exception
    {
        boolean isAnnotation = MyTestClass.class.isAnnotationPresent(MyTestAnnotation.class);
        if(isAnnotation) {
            MyTestAnnotation myTestAnnotation = MyTestClass.class.getAnnotation(MyTestAnnotation.class);
            System.out.println("id:" + myTestAnnotation.id());
            System.out.println("name:" + myTestAnnotation.name());
        }

        isAnnotation = MyTest2Class.class.isAnnotationPresent(MyTestAnnotation.class);
        if(isAnnotation) {
            System.out.println("");
            MyTestAnnotation myTestAnnotation = MyTest2Class.class.getAnnotation(MyTestAnnotation.class);
            System.out.println("id:" + myTestAnnotation.id());
            System.out.println("name:" + myTestAnnotation.name());
        }

        isAnnotation = MySubTestClass.class.isAnnotationPresent(MyTestAnnotation.class);
        if(isAnnotation) {
            System.out.println("");
            MyTestAnnotation myTestAnnotation = MySubTestClass.class.getAnnotation(MyTestAnnotation.class);
            System.out.println("id:" + myTestAnnotation.id());
            System.out.println("name:" + myTestAnnotation.name());
        }

        System.out.println("获取类成员属性和方法的注解");
        //获取类成员属性和方法的注解
       
    Field a = MyTestClass.class.getDeclaredField("myflag");
        a.setAccessible(true);
        //获取一个成员变量上的注解
       
    CheckNum check = a.getAnnotation(CheckNum.class);

        if ( check != null ) {
            System.out.println("check value:"+check.value());
        }

        Method testMethod = MyTestClass.class.getDeclaredMethod("checkMyStr", String.class);

        if ( testMethod != null ) {
            // 获取方法中的注解
           
    Annotation[] ans = testMethod.getAnnotations();
            for( int i = 0;i < ans.length;i++) {
                System.out.println("method  annotation:"+ans[i].annotationType().getSimpleName());
            }
        }
    }

    输出结果:

    id:-1

    name:hello world

    id:1000

    name:I love this game

    id:-1

    name:hello world

    获取类成员属性和方法的注解

    check value:true

    method  annotation:CheckString

    method  annotation:CheckNum

    符合输出预期。

    
    
  • 相关阅读:
    九度OJ 1010 A+B
    九度OJ 1052 找x
    oracle数据库创建备份与恢复 脚本
    在select标签中添加a标签
    如何在select标签中使用a标签跳转页面
    网站访问不了
    js实现input的赋值
    PHP如何实现百万级数据导出
    互联网产品需求管理杂思2需求收集,互联网营销 狼人:
    做网站用UTF8还是GB2312?,互联网营销 狼人:
  • 原文地址:https://www.cnblogs.com/asker009/p/9366857.html
Copyright © 2011-2022 走看看