1.什么是注解
2.基本的Annotation
1.限定父类重写方法:@Override
当子类重写父类方法时,子类可以加上这个注解,那这有什么什么用?这可以确保子类确实重写了父类的方法,避免出现低级错误
2.标示已过时:@Deprecated
List list = new ArrayList();
list.add(20);
List<String> ls = list;
System.out.println(ls.get(0));
则会抛出堆污染异常
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at Test.Test1.main(Test1.java:29)
注意:可变参数更容易引发堆污染异常,因为java不允许创建泛型数组,可变参数恰恰是数组。
抑制这个警告的方法有三个:
3.自定义注解
1.定义注解非常的简单,如下
public @interface Test{}然后这个注解就可以用在别的地方
4.JDK的元Annotation
1.使用@Retention
这个注解是用来修饰注解定义的,作用是被修饰的注解可以保存多久,这个注解需要使用参数。
这个参数的类型是RetentionPolicy,所以使用这个注解就要对value赋值。
value的值有且仅有三个:
->RetenionPolicy.CLASS 编译器把该注解记录在class文件中。当运行java程序时,JVM不可获取注解信息。这是默认值!
->RetenionPolicy.RUNTIME 编译器把该注解记录在class文件中。当运行java程序时,JVM可获取注解信息,程序可以通过反射获取该注解信息
->RetenionPolicy.SOURCE 该注解只保存在源代码中,编译器直接丢弃该注解
例如:@Retention(value = RetenionPolicy.SOURCE ) 可简写为 @Retention(RetenionPolicy.SOURCE )
2.使用@Target
@Target也只能修饰一个注解定义,作用是指定被修饰的注解能用于修饰哪些程序单元,@Target也包含了一个value值,他的值只能是下面的:ElementType.
取值 | 注解使用范围 |
METHOD | 可用于方法上 |
TYPE | 可用于类或者接口上 |
ANNOTATION_TYPE | 可用于注解类型上(被@interface修饰的类型) |
CONSTRUCTOR | 可用于构造方法上 |
FIELD | 可用于域上 |
LOCAL_VARIABLE | 可用于局部变量上 |
PACKAGE | 用于记录java文件的package信息 |
PARAMETER | 可用于参数上 |
例如:
@Target(ElementType.METHOD) (这是简写)
public @interface Action()
@interface 不是interface,是注解类
是jdk1.5之后加入的,java没有给它新的关键字,所以就用@interface 这么个东西表示了
这个注解类,就是定义一个可用的注解,包括这个注解用于什么地方,是类,还是方法,还是property,还是方法入参等等,还有这个注解是否编译后进入class
比如我们知道的用于javadoc的注解,是不进入class文件的。然后在后面你就可以用这个注解写代码了。
总的来说,这就是一个生成javadoc时用到的注释类
3.使用@Documented
这个注解用于指定被修饰的注解类将被javadoc工具提取成文档,如果定义注解类时使用了这个注解修饰,则所有使用该注解修饰的程序员苏API文档将会包含该注解说明。
例如:
@Documented public @interface Testable{}
4.使用@Inherited
这个注解指定被他修饰的注解将具有继承性——如果某个类使用了@Xxx,则其子类将自动被@Xxx修饰
5.使用@Result
作用是在同一个程序元素前使用多个相同类型的注解
在java8之前只能通过@Results配置,java8简化了它的写法
例如:
@test(age=5)
@test(age=8)
public void resultTest(){}
6.使用类型注解
让我们先看几个例子:
- 创建类实例
new@Interned MyObject();
- 类型映射
myString = (@NonNull String) str;
- implements 语句中
class UnmodifiableList<T> implements@Readonly List<@Readonly T> { ... }
- throw exception声明
等等地方都可以用类型注解void monitorTemperature() throws@Critical TemperatureException { ... }
新增ElementType.TYPE_USE 和ElementType.TYPE_PARAMETER(在Target上)
新增的两个注释的程序元素类型 ElementType.TYPE_USE 和 ElementType.TYPE_PARAMETER 用来描述注解的新场合 。 ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中。 ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中(eg:声明语句、泛型和强制转换语句中的类型)。还是那句话,这些注解本身是没有意义的。要靠自己实现类型注解的检查框架,或者第三方,类型注解最大的意义在于,让编译器执行更严格的检查,保证代码更加的健壮。