写 Java 的时候时不时能接触到注解的代码。就是那个在类或者方法上出现 @ 符号的地方,比如在方法中使用泛型的时候,如果没有检查类型,IDEA 会自动警告提示,此时在方法名上添加 @SuppressWarnings(“unchecked”) 就可以消除这个警告
那么今天就先从这个 SuppressWarnings 入手开始简单分析下注解是什么
1 2 3 4 5
| @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings { String[] value(); }
|
我们看到 SuppressWarnings 是一个 @interface 的 Java 类型,表示它是一个 Annataion (注解)
看到它被 @Retention 和 @Target 进行了修饰,用来修饰注解的叫做元注解,在 Java 中有这样几个元注解:
@Retention、 @Target、 @Document、 @Inherited和@Repeatable(Java 8 加入)
@Retention
表示被修饰的注解生效范围,像 SuppressWarnings 中是 SOURCE,表示 SuppressWarnings 只是作用在源代码,不会生成到 class 文件中。其他的几个作用范围是:
默认值,表示注解会在 class 文件中存在,但运行时无法获取到
表示注解会在 class 文件中存在,在运行时可以通过反射获取到
因此,如果是我们自定义注解,那么肯定要使用 RUNTIME 的方式才有意义
@Target
表示被修饰的注解作用的范围
- ElementType.TYPE 作用于类、接口(包括注解类型),枚举
- ElementType.FIELD 作用于域字段、枚举常量
- ElementType.METHOD 作用于方法
- ElementType.PARAMETER 作用于方法参数
- ElementType.CONSTRUCTOR 作用于构造方法
- ElementType.LOCAL_VARIABLE 作用于局部变量
- ElementType.ANNOTATION_TYPE)作用于注解
- ElementType.PACKAGE) 作用于包
- ElementType.TYPE_PARAMETER 作用于类型参数,即泛型类、泛型方法、泛型接口 (Java 8 加入)
- ElementType.TYPE_USE 类型使用(Java 8 加入)
所以 SuppressWarnings 是可以用于类,接口,方法,成员变量,方法参数,构造方法,局部变量的注解
以上两个注解是使用得比较多的,其他的几个元注解今天暂不介绍。注解在 Java 代码中主要是用来读取数据用的,既然我们定义好了自己的注解,那么读取的话,使用的是反射
读取注解
判断是否存在对应的 Annatation 对象
获取对应的 Annatation 对象
获取所有对应的 Annatation 对象组
给一个自定义注解例子,并获取值
在这个例子中,自定义注解 MyAnnotation,作用于类,域字段以及方法
对 Test 类以及它的字段和方法都使用该注解修饰,并通过反射获取它们的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation { String[] value(); }
@MyAnnotation("className") public class Test { @MyAnnotation("fieldName") String field;
@MyAnnotation("methodName") public void method(){
}
public static void main(String[] args) { Class<Test> klass = Test.class;
// 判断是否存在类注解 boolean hasClassAnno = klass.isAnnotationPresent(MyAnnotation.class); if (hasClassAnno){ // 获取该注解 MyAnnotation myAnnotation = klass.getAnnotation(MyAnnotation.class); // 提取注解的值 System.out.println(Arrays.toString(myAnnotation.value())); }
try { Field field = klass.getDeclaredField("field"); if (field.isAnnotationPresent(MyAnnotation.class)){ MyAnnotation myAnnotation = field.getAnnotation(MyAnnotation.class); System.out.println(Arrays.toString(myAnnotation.value())); }
Method method = klass.getMethod("method"); if (method.isAnnotationPresent(MyAnnotation.class)){ MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class); System.out.println(Arrays.toString(myAnnotation.value())); } } catch (NoSuchFieldException | NoSuchMethodException e) { e.printStackTrace(); } } }
|
今天的介绍就到这里,现在是疫情攻坚期,祈祷武汉尽快挺过难关,中国尽快挺过难关