java自定义注解
参考博客:https://blog.csdn.net/briblue/article/details/73824058
感觉这篇文章写得非常好,讲的很清楚明白,易于理解;例子也很不错,做个记录:
代码:
package com.cy.test;
import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 自定义注解测试类
*/
@MyAnnotation(id = 100, msg = "hello annotation")
public class TestAnnotation{
@Check("hi")
//相当于 @Check(value = "hi"),如果属性名是value的话,在使用注解时,该属性名可以省略
private int a;
@Perform
public void testMethod(){
}
public static void main(String[] args) {
//获取类上的注解
TestAnnotation t = new TestAnnotation();
boolean r = t.getClass().isAnnotationPresent(MyAnnotation.class);//是否应用了某个注解
System.out.println(r);
if(r){
MyAnnotation a = t.getClass().getAnnotation(MyAnnotation.class);//获取Annotation对象 java.lang.annotation.Annotation是所有注解的老祖宗。
System.out.println("id:" + a.id());
System.out.println("msg:" + a.msg());
}
Annotation annotation[] = t.getClass().getAnnotations(); //获取所有注解
for(Annotation an : annotation){
System.out.println(an.annotationType()); //获取注解类型:interface com.cy.test.MyAnnotation
}
//获取成员变量上的注解
Field fields[] = t.getClass().getDeclaredFields();
Field fielda = null;
for(Field f : fields){
System.out.println(f.getName() +"," +f.getType() +"," + f.getGenericType() + "," + f.getModifiers());
if(f.getName().equals("a")) fielda = f;
}
fielda.setAccessible(true);
Check check = fielda.getAnnotation(Check.class);
System.out.println("check value:"+check.value());
//获取方法上的注解
try {
Method testMethod = t.getClass().getDeclaredMethod("testMethod");
Annotation annotations[] = testMethod.getAnnotations();
for(Annotation a : annotations) {
System.out.println(a.annotationType().getSimpleName());
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
/**
* 自定义的注解 类上
* 注解在使用时必须给属性赋值,除非你使用了default关键字为属性指定了默认值。
* 如果属性只有一个,并且属性名是value时,使用注解时value可以省略不写。
* 如果属性是一个数组,使用注解时,数组值只有一个时,数组的大括号是可以省略的。
*/
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@interface MyAnnotation {
int id() default 0;
String msg() default "defaule msg";
}
/**
* 注解 属性上
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Check {
String value();
}
/**
* 注解 方法上
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Perform {
}
console:
true id:100 msg:hello annotation interface com.cy.test.MyAnnotation a,int,int,2 check value:hi Perform
@Retention
Retention 的英文意为保留期的意思。当 @Retention 应用到一个注解上的时候,它解释说明了这个注解的的存活时间。
它的取值如下:
RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。这意味着可以通过反射获取到这个注解的信息。
我们可以这样的方式来加深理解,@Retention 去给一张标签解释的时候,它指定了这张标签张贴的时间。@Retention 相当于给一张标签上面盖了一张时间戳,时间戳指明了标签张贴的时间周期。
@Target
你可以这样理解,当一个注解被 @Target 注解时,这个注解就被限定了运用的场景。
类比到标签,原本标签是你想张贴到哪个地方就到哪个地方,但是因为 @Target 的存在,它张贴的地方就非常具体了,比如只能张贴到方法上、类上、方法参数上等等。@Target 有下面的取值
ElementType.TYPE 作用于接口、类、枚举、注解
ElementType.FIELD 作用于属性、枚举的常量
ElementType.METHOD 作用于方法
ElementType.PARAMETER 作用于方法参数,可以给一个方法内的参数进行注解
ElementType.CONSTRUCTOR 作用于构造方法,可以给构造方法进行注解
ElementType.LOCAL_VARIABLE 作用于局部变量,可以给局部变量进行注解
ElementType.ANNOTATION_TYPE 作用于注解,可以给一个注解进行注解
ElementType.PACKAGE 作用于包,可以给一个包进行注解
ElementType.TYPE_PARAMETER 作用于泛型,即泛型方法、泛型类和泛型接口
@Documented
设置注解是否可以生成到帮助文档中。使用javadoc.exe工具可以从程序源代码中抽取类、方法、属性等注释形成一个源代码配套的API帮助文档,而该工具抽取时默认不包括注释内容。如果使用的注解被@Documented标注,那么该注解就能被javadoc.exe工具提取到API文档。
@Inherited
设置注解是否支持继承。Inherited的英文意思是继承,但是这个继承和我们平时理解的继承大同小异,一个被@Inherited注解了的注解修饰了一个父类,则它的子类也继承了父类的注解。
另外,上面例子代码中f.getModifiers()得到的是2,为什么?
JAVA 反射机制中,Field的getModifiers()方法返回int类型值表示该字段的修饰符。
其中,该修饰符是java.lang.reflect.Modifier的静态属性。
对应表如下:
PUBLIC: 1
PRIVATE: 2
PROTECTED: 4
STATIC: 8
FINAL: 16
SYNCHRONIZED: 32
VOLATILE: 64
TRANSIENT: 128
NATIVE: 256
INTERFACE: 512
ABSTRACT: 1024
STRICT: 2048
--
浙公网安备 33010602011771号