Java的自定义注解使用实例
概念
Java 有五个元注解,自动继承java.lang.annotation.Annotation。
什么是元注解,可以理解为其他普通注解进行解释说明
@Target 该注解的使用范围,限定应用场景。枚举类 ElemenetType 中
- TYPE: 类,接口
- FIELD: 字段,枚举的常量
- METHOD: 函数 (方法)
- PARAMETER: 参数
- CONSTRUCTOR: 构造函数
- ANNOTATION_TYPE: 注解类型
- LOCAL_VARIABLE: 局部变量
- PACKAGE: 包
@Retention 该注解的生存周期,相当于时间戳。枚举类型 RetentionPolicy 中
- SOURCE: 在源文件中有效,编译后会被丢弃(如 @Override,@Deprecated)
- CLASS: 在 class 文件中有效,在 jvm 丢弃
- RUNTIME: 在运行时有效,class 文件保留,jvm 运行时保留 (很多框架运用反射调用)
@Documented
javadoc 文档生成工具的使用
@Inherited
允许子类继承父类中的注解。
@Repeatable
同一种注解可多次使用
作用
- 注释,解释,通过代码的标识元数据生成 doc 文档;
- 使用反射,通过代码标识的元数据对代码进行分析;
- 编译检查,通过代码标识的元数据让编译器进行基本检查。
实例
定义一个普通的注解,
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 < 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 不善于用语言表达,所以可能有很多人没看懂,可以看下
一个大佬讲解的注解说明 (简单易懂)