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

    符合输出预期。

    
    
  • 相关阅读:
    ZOJ 3332 Strange Country II
    ZOJ 3331 Process the Tasks(双塔DP)
    ZOJ 3326 An Awful Problem(模拟)
    HDU 1796 How many integers can you find(容斥原理)
    HDU 4059 The Boss on Mars(容斥原理)
    HDU 4135 Co-prime(容斥原理)
    HDU 5677 ztr loves substring(回文串加多重背包)
    CodeForces 668B Little Artem and Dance
    CodeForces 667A Pouring Rain
    Java实现 LeetCode 764 最大加号标志(暴力递推)
  • 原文地址:https://www.cnblogs.com/asker009/p/9366857.html
Copyright © 2011-2022 走看看