Java中常见的注解
JDK自带的注解
1.@Override 表示重写了此方法
2.@Deprecated 表示这个方法过时了,不建议使用,Ide会在方法上划横线
3.@SuppressWarnings(“deprecation”) 关闭方法中出现的警告
@SuppressWarnings注解参数常见用法:
1.deprecation:去除不赞成使用类的警告
2.serial:去除当在可序列化的类上缺少 serialVersionUID 定义时的警告
3.finally:去除任何 finally 子句不能正常完成时的警告
4.rawtypes:去除传参数时也要带泛型的警告
5.unchecked:去除执行了未检查的转换时的警告,例如当使用集合时没有用泛型来指定集合保存的类型
6.unused:去除对未使用代码的警告
7.all:去除所有类型的警告
元注解
元注解的作用就是注解其他注解,一般我们使用自定义注解时,就需要用元注解来标注我们自己的注解
@Target:
说明了Annotation被修饰的范围,在Annotation类型的声明中使用了@Target可更加清晰其修饰的目标,声明的范围包括:
1.@Target(ElementType.TYPE):用于类、接口(包括Annotation类型)或枚举
2.@Target(ElementType.FIELD):用于类的成员变量(包括枚举常量)
3.@Target(ElementType.METHOD):用于方法
4.@Target(ElementType.PARAMETER):用于参数
5.@Target(ElementType.CONSTRUCTOR):用于构造器
6.@Target(ElementType.LOCAL_VARIABLE):用于局部变量
7.@Target(ElementType.ANNOTATION_TYPE):用于Annotation类型
8.@Target(ElementType.PACKAGE):用于包
9.@Target(ElementType.TYPE_PARAMETER):1.8新增,Type parameter declaration
10.@Target(ElementType.TYPE_USE):1.8新增,Use of a type
ElementType源码:
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
@Retention:
定义了该Annotation被保留的时间长短,有些只在源码中保留,有时需要在编译成的class中保留,有些需要程序运行时候保留。即描述注解的生命周期。声明类型包括:
1.@Retention(RetentionPolicy.SOURCE) 在源文件保留,例如@Override就是用了@Retention(RetentionPolicy.SOURCE)
2.@Retention(RetentionPolicy.CLASS) 在class中保留,自定义注解默认是在class中保留,对于为什么要使用CLASS不是很明白,这有一篇文章对两者进行了讨论,但我还是不是很明确,希望日后能找到答案
3.@Retention(RetentionPolicy.RUNTIME) 运行时保留,可以通过反射获取,例如@Deprecated使用了@Retention(RetentionPolicy.RUNTIME)
RetentionPolicy源码:
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
@Documented:
它表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中,是一个标记注解,没有成员。
@Inherited:
它也是一个标记注解,它的作用是,被它标注的类型是可被继承的,比如一个class被@Inherited标记,那么一个子类继承该class后,则这个annotation将被用于该class的子类。
注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。对于这句话的理解通过如下实例说明:
自定义一个注解类,使用@Inherited,配合使用@Retention(RetentionPolicy.RUNTIME)以通过反射观察注解的继承情况:
package com.lyh.study.annotation;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Created by liuyunhui on 2020-03-11 16:05.
* description:
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface InheritedDemo {
String name();
}
新建一个父类:
package com.lyh.study.annotation;
/**
* Created by liuyunhui on 2020-03-11 16:11.
* description:
*/
@InheritedDemo(name = "注解可被继承的父类")
public abstract class InheritedParentClass {
@InheritedDemo(name = "父类中被重写的方法")
public void override(){
System.out.println("会被重写的方法");
}
@InheritedDemo(name = "父类中没被重写的方法")
public void notOverride(){
System.out.println("不被重写的方法");
}
@InheritedDemo(name = "父类中的抽象方法")
public abstract void abstractMethod();
}
新建一个子类,继承上边的父类:
package com.lyh.study.annotation;
/**
* Created by liuyunhui on 2020-03-11 16:11.
* description:
*/
public class InheritedChildClass extends InheritedParentClass{
@Override
public void abstractMethod() {
System.out.println("实现父类的抽象方法");
}
@Override
public void override() {
super.override();
System.out.println("重写了父类的方法");
}
}
测试:
package com.lyh.study.annotation;
import org.junit.Test;
public class TestClass {
@Test
public void test1() {
Class<InheritedChildClass> inheritedChildClassClass = InheritedChildClass.class;
if(inheritedChildClassClass.isAnnotationPresent(InheritedDemo.class)){
final InheritedDemo annotation = inheritedChildClassClass.getAnnotation(InheritedDemo.class);
System.out.println("子类获取到父类的注解,name:"+annotation.name());
}else {
System.out.println("子类获取不到父类的注解");
}
}
}
结果输出:
注意:如果自定义注解InheritedDemo没有使用注解@Retention(RetentionPolicy.RUNTIME),结果为子类获取不到父类的注解
测试:
//抽象方法的测试
try {
final Method abstractMethod = inheritedChildClassClass.getMethod("abstractMethod", new Class[]{});
if(abstractMethod.isAnnotationPresent(InheritedDemo.class)){
final InheritedDemo annotation = abstractMethod.getAnnotation(InheritedDemo.class);
System.out.println("子类实现了父类抽象方法,获取到父类抽象方法的注解,name:"+annotation.name());
}else{
System.out.println("子类实现了父类抽象方法,获取不到父类的注解");
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
结果输出:
测试:
//重写方法的测试
try {
final Method overrideMethod = inheritedChildClassClass.getMethod("override", new Class[]{});
if(overrideMethod.isAnnotationPresent(InheritedDemo.class)){
final InheritedDemo annotation = overrideMethod.getAnnotation(InheritedDemo.class);
System.out.println("子类重写了父类方法,获取到父类方法的注解,name:"+annotation.name());
}else{
System.out.println("子类重写了父类方法,获取不到父类方法的注解");
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
System.out.println("----------------------------");
//未重写方法的测试
try {
final Method notOverrideMethod = inheritedChildClassClass.getMethod("notOverride", new Class[]{});
if(notOverrideMethod.isAnnotationPresent(InheritedDemo.class)){
final InheritedDemo annotation = notOverrideMethod.getAnnotation(InheritedDemo.class);
System.out.println("子类未重写父类方法,获取到父类方法的注解,name:"+annotation.name());
}else{
System.out.println("子类未重写父类方法,获取不到父类方法的注解");
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
结果输出:
新建一个接口:
package com.lyh.study.annotation;
/**
* Created by liuyunhui on 2020-03-11 16:11.
* description:
*/
@InheritedDemo(name = "注解在接口上")
public interface InheritedParentInterface {
@InheritedDemo(name = "注解在接口的方法上")
void abstractMethod();
}
接口实现类:
package com.lyh.study.annotation;
/**
* Created by liuyunhui on 2020-03-11 16:11.
* description:
*/
public class InheritedParent2Class implements InheritedParentInterface{
@InheritedDemo(name = "被重写的方法的注解")
public void override(){
System.out.println("会被重写的方法");
}
@InheritedDemo(name = "未被重写的方法的注解")
public void notOverride(){
System.out.println("不被重写的方法");
}
@Override
public void abstractMethod() {
System.out.println("实现的抽象方法");
}
}
测试:
Class<InheritedParent2Class> inheritedParent2Class = InheritedParent2Class.class;
//实现的接口类测试
if (inheritedParent2Class.isAnnotationPresent(InheritedDemo.class)) {
final InheritedDemo annotation = inheritedParent2Class.getAnnotation(InheritedDemo.class);
System.out.println("实现类,获取到实现接口上的注解,name:" + annotation.name());
} else {
System.out.println("实现类,未获取到实现接口上的注解");
}
System.out.println("----------------------------");
//实现的接口类方法测试
try {
final Method abstractMethod = inheritedParent2Class.getMethod("abstractMethod", new Class[]{});
if(abstractMethod.isAnnotationPresent(InheritedDemo.class)){
final InheritedDemo annotation = abstractMethod.getAnnotation(InheritedDemo.class);
System.out.println("实现类实现的接口类方法,获取到接口类方法的注解,name:"+annotation.name());
}else{
System.out.println("实现类实现的接口类方法,未获取到接口类方法的注解");
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
结果输出:
新建一个子类,继承接口实现类InheritedParent2Class :
package com.lyh.study.annotation;
/**
* Created by liuyunhui on 2020-03-11 16:11.
* description:
*/
public class InheritedChild2Class extends InheritedParent2Class{
@Override
public void abstractMethod() {
System.out.println("实现父类的抽象方法");
}
@Override
public void override() {
super.override();
System.out.println("重写了父类的方法");
}
}
测试:
System.out.println("----------------------------");
Class<InheritedChild2Class> inheritedChild2Class = InheritedChild2Class.class;
//继承实现了接口的类的类测试
if (inheritedChild2Class.isAnnotationPresent(InheritedDemo.class)) {
final InheritedDemo annotation = inheritedChild2Class.getAnnotation(InheritedDemo.class);
System.out.println("子类,父类实现了接口类,获取到实现接口上的注解,name:" + annotation.name());
} else {
System.out.println("子类,父类实现了接口类,未获取到实现接口上的注解");
}
System.out.println("----------------------------");
//子类方法测试
try {
final Method abstractMethod = inheritedChild2Class.getMethod("abstractMethod", new Class[]{});
if(abstractMethod.isAnnotationPresent(InheritedDemo.class)){
final InheritedDemo annotation = abstractMethod.getAnnotation(InheritedDemo.class);
System.out.println("子类,父类实现了接口类,获取到的注解,name:"+annotation.name());
}else{
System.out.println("子类,父类实现了接口类,未获取到注解");
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
System.out.println("----------------------------");
//重写方法的测试
try {
final Method overrideMethod = inheritedChild2Class.getMethod("override", new Class[]{});
if(overrideMethod.isAnnotationPresent(InheritedDemo.class)){
final InheritedDemo annotation = overrideMethod.getAnnotation(InheritedDemo.class);
System.out.println("子类,父类实现了接口类,重写父类方法,获取到的注解,name:"+annotation.name());
}else{
System.out.println("子类,父类实现了接口类,重写父类方法,未获取到注解");
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
System.out.println("----------------------------");
//未重写方法的测试
try {
final Method notOverrideMethod = inheritedChild2Class.getMethod("notOverride", new Class[]{});
if(notOverrideMethod.isAnnotationPresent(InheritedDemo.class)){
final InheritedDemo annotation = notOverrideMethod.getAnnotation(InheritedDemo.class);
System.out.println("子类,父类实现了接口类,未重写父类方法,获取到的注解,name:"+annotation.name());
}else{
System.out.println("子类,父类实现了接口类,未重写父类方法,未获取到注解");
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
结果输出: