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
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;

@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> say()
{
    System.out.println(</span>"Hello,Java Annotation"<span style="color: rgba(0, 0, 0, 1)">);
}

}

@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
{

</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String name;


</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;


</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> say()
{
    System.out.println(</span>"Hello,Java Annotation"<span style="color: rgba(0, 0, 0, 1)">);
}

}

@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
{

</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String name;

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;
@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Person()
{

}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> say()
{
    System.out.println(</span>"Hello,Java Annotation"<span style="color: rgba(0, 0, 0, 1)">);
}

}

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

@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
{

</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String name;

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;<br>
@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Person()
{

}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> say()
{
    System.out.println(</span>"Hello,Java Annotation"<span style="color: rgba(0, 0, 0, 1)">);
}

}

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

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

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;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> String name() <span style="color: rgba(0, 0, 255, 1)">default</span> <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> 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
{

</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String name;

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;

</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Person()
{

}


</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> say()
{
    System.out.println(</span>"Hello,Java Annotation"<span style="color: rgba(0, 0, 0, 1)">);
}

}

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

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;

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;

</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Person()
{

}

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> say()
{
    System.out.println(</span>"Hello,Java Annotation"<span style="color: rgba(0, 0, 0, 1)">);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args)
{
    </span><span style="color: rgba(0, 0, 255, 1)">boolean</span> hasAnnotation = Person.<span style="color: rgba(0, 0, 255, 1)">class</span>.isAnnotationPresent(Test.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);

    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (hasAnnotation)
    {
        Test test </span>= Person.<span style="color: rgba(0, 0, 255, 1)">class</span>.getAnnotation(Test.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);

        System.out.println(</span>"age:" +<span style="color: rgba(0, 0, 0, 1)"> test.age());
        System.out.println(</span>"name:" +<span style="color: rgba(0, 0, 0, 1)"> test.name());
        System.out.println(</span>"className:" +<span style="color: rgba(0, 0, 0, 1)"> test.className());
    }<br>     }<br>}<br></span></pre>

输出结果

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;

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;

</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Person()
{

}
@Method(say </span>= "hello"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> say()
{
    System.out.println(</span>"Hello,Java Annotation"<span style="color: rgba(0, 0, 0, 1)">);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args)
{
    </span><span style="color: rgba(0, 0, 255, 1)">boolean</span> hasAnnotation = Person.<span style="color: rgba(0, 0, 255, 1)">class</span>.isAnnotationPresent(Test.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);

    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (hasAnnotation)
    {
        Test test </span>= Person.<span style="color: rgba(0, 0, 255, 1)">class</span>.getAnnotation(Test.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);

        System.out.println(</span>"age:" +<span style="color: rgba(0, 0, 0, 1)"> test.age());
        System.out.println(</span>"name:" +<span style="color: rgba(0, 0, 0, 1)"> test.name());
        System.out.println(</span>"className:" +<span style="color: rgba(0, 0, 0, 1)"> test.className());
    }

    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
    {
        java.lang.reflect.Field field </span>= Person.<span style="color: rgba(0, 0, 255, 1)">class</span>.getDeclaredField("name"<span style="color: rgba(0, 0, 0, 1)">);

        field.setAccessible(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);

        Field check </span>= field.getAnnotation(Field.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);

        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (check != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
        {
            System.out.println(</span>"check value:" +<span style="color: rgba(0, 0, 0, 1)"> check.name());
        }

        java.lang.reflect.Method method </span>= Person.<span style="color: rgba(0, 0, 255, 1)">class</span>.getDeclaredMethod("say"<span style="color: rgba(0, 0, 0, 1)">);  

        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (method != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
        {
            Annotation[] ans </span>=<span style="color: rgba(0, 0, 0, 1)"> method.getAnnotations();
            </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; ans.length; i++<span style="color: rgba(0, 0, 0, 1)">)
            {
                System.out.println(</span>"method annotation:" +<span style="color: rgba(0, 0, 0, 1)"> ans[i].annotationType().getSimpleName());
            }
         }

    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (NoSuchFieldException e)
    {
        e.printStackTrace();
    }</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (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(</span>"15"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;

</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Person()
{

}

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> say()
{
    System.out.println(</span>"Hello,Java Annotation"<span style="color: rgba(0, 0, 0, 1)">);
}

@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String toString()
{
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> "name = " + name + "\n" + "age = " +<span style="color: rgba(0, 0, 0, 1)"> age;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args)
{
    Person person </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Person();
    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
    {
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">取得成员变量的值</span>
        Field field = Person.<span style="color: rgba(0, 0, 255, 1)">class</span>.getDeclaredField("name"<span style="color: rgba(0, 0, 0, 1)">);
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开权限</span>
        field.setAccessible(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">判断属性是否有注解</span>
        <span style="color: rgba(0, 0, 255, 1)">if</span> (field.isAnnotationPresent(Test.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">))
        {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取属性上的注解值</span>
            Test test = field.getAnnotation(Test.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
            String name </span>=<span style="color: rgba(0, 0, 0, 1)"> test.value();
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">赋值</span>

field.set(person,name);
}

        Field field1 </span>= Person.<span style="color: rgba(0, 0, 255, 1)">class</span>.getDeclaredField("age"<span style="color: rgba(0, 0, 0, 1)">);
        field1.setAccessible(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (field1.isAnnotationPresent(Test.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">))
        {
            Test test </span>= field1.getAnnotation(Test.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">int</span> age =<span style="color: rgba(0, 0, 0, 1)"> Integer.valueOf(test.value());
            field1.set(person,age);
        }
        System.out.println(person);

    }</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e)
    {
        e.printStackTrace();
    }

}

}

输出

name = zhangsan
age = 15

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

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

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

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