官方:注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的一部分。注解对于代码的运行效果没有直接影响。
人话:注解类似于标签,相当于给一个东西贴上标签,让编译器能更好的认识它,从而进行处理。
元数据指的就是用来描述数据的数据,即注解是一种用来描述数据的数据。
元注解只是在使用的范围上有限制,它是用来给注解添加注解的。元注解一共就只有@Retention、@Documented、@Target、@Inherited、@Repeatable 这5种。
字面意思为保留。当它应用到一个注解上的时候,就可以解释说明当前注解作用的时间。这个保留策略(RetentionPolicy)它是一个枚举型,如果没有注解中没有声明元注解@Retention,则默认为RetentionPolicy.CLASS。
RetentionPolicy.CLASS:表明仅存在于源文件和经编译器编译后生成的字节码文件,在运行时VM不会保留注解。
RetentionPolicy.SOURCE:仅存在于源文件,经编译器编译后便丢弃相应的注解。
RetentionPolicy.RUNTIME:存在于源文件、编译后的字节码文件,还保留在运行时的VM中,可通过反射读取相应注解。
如果定义Annotation类时使用了@Documented修饰,则所有使用该Annotation修饰的程序元素的API文档中将会包含该Annotation说明。也就是说我们可以用它来编写文档。
目标。即这个元注解限制了被修饰注解所能作用的范围。它也是一个枚举型,但是当注解中没有声明元注解@Target,则默认为能作用于所有地方。
ANNOTATION_TYPE:给一个注解进行注解。
CONSTRUCTOR:给构造方法进行注解。
FIELD:给属性进行注解。
LOCAL_VARIABLE:给局部变量进行注解。
METHOD:给方法进行注解。
PACKAGE:给一个包进行注解。
PARAMETER:给一个方法中的参数进行注解。
TYPE:可以给一个类型进行注解,比如类、接口、枚举
遗传。类似于类的继承关系。举个例子,如果A这个类被xx注解,现在B这个类是A的子类,那么B就自动拥有这个注解。
可重复。即注解的值可以同时取多个 ,就像一个人可以有多个身份,他可以是学生、程序员、DJ...
@Override:用于告诉编译器我们需要覆写超类的当前方法。
@Deprecated:告知编译器,某一属性、方法等过时了,我们常见一个方法被划了一根线就说明那个方法是被@Deprecated注解过的。
@SuppressWarnings:告知编译器忽略指定警告。在我们使用了这个后编译器将不会报出警告信息。
@SafeVarargs:参数安全类型注释,它会阻止编译器发出unchecked这样的警告,但是如果在实际应用中,开发者写了这个注解,但是参数实际是有错误的,这时它虽然不会在编译阶段发出警告,但是在运行时还是会抛出异常。
@FunctionalInterface:为响应函数式编程的号召,在java1.8中加入了这个注解。用户告知编译器,检查这个接口,保证该接口是函数式接口,即只能包含一个抽象方法,否则就会编译出错。
在自定义注解之前,我们还需要了解下注解的属性。
注解的属性也叫成员变量,且注解只有成员变量,没有方法。但是注解的成员变量的声明同一般的成员变量声明有很大的区别。
注解的成员变量在注解的定义中以“无形参的方法”来声明。返回值即成员变量类型,方法名即变量名。并且我们可以通过default关键字为成员变量赋一个初始值。
import java.lang.annotation.*;
//元注解
@Documented
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
//通过@interface关键字来声明一个注解
public @interface TestAnnotation{
//-> String name
String name();
//-> String website = "hello"
String website()default "hello";
//->int revision = 1
int revision()default 1;
}
通过上面代码,我们就简单的自定义了一个注解,可以看到这个注解仅包括元注解、属性,但它也算是一个完整的注解了。
JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
这是我们之前了解过的反射机制,可以看到反射机制是作用于运行状态中的,所以这就限制了我们去动态解析注解的范围——必须要在运行状态还保留。这就涉及到@Retention这个元注解了,回顾一下,发现只有被声明为RUNTIME才能利用反射机制进行解析了。
@TestAnnotation(name="Mike")
public class Annotation {
public static void main(String[] args) {
System.out.println("I am main method");
//Class类对象的isAnnotationPresent能够判断出是否应用了某个注解
boolean hasAnnotation = Annotation.class.isAnnotationPresent(TestAnnotation.class);
System.out.println(hasAnnotation);
if (hasAnnotation){
//获取类的注解
TestAnnotation testAnnotation = Annotation.class.getAnnotation(TestAnnotation.class);
//访问注解中的成员变量
System.out.println("name: "+testAnnotation.name());
System.out.println("website: "+testAnnotation.website());
System.out.println("revision: "+testAnnotation.revision());
}
}
}
上面我们只获取了类的注解,并对其所有成员变量进行了访问,但是我们还能获取方法中及成员变量的注解,大致写法都是类似的。
本文参考自一位大神的博客,加了些许自己的理解,供大家参考,如有不足请指出!谢谢!
https://blog.csdn.net/briblue/article/details/73824058