Annotation
注解字面意思就是对代码进行解释的信息,对代码的执行没有影响。注解能被注释解析工具或者编译器解析。
注解的作用
-
指导编译器的工作
Java提供了三个常用的注解(
@Deprecated
,@Override
,@SuppressWarnings
),@Override
就是告诉编译器这个方法是覆写父类的方法。 -
编译时的指示器
-
运行时的指示器
注解的一些基本概念
-
注解都是以
@
开始,然后跟上注解名,@
就是告诉编译器这是个注解。例如@Override
就是告诉这是个注解,注解名是Override
。 -
注解可以使用在类、接口、变量和方法上。例如下面的代码注解就是用在方法上。
@Override void myMethod() { //Do something }
内置的注解
-
@Override
当子类覆写父类方法时需要使用这个注解,使用这个注解能使代码具有更高可读性和维护性,例如父类修改了方法名,子类也必须修改成一致,否则编译器就会提示错误。
public class MyParentClass { public void method() { System.out.println("父类方法"); } } public class MyChildClass extends MyParentClass { @Override public void method() { System.out.println("子类方法"); } }
-
@Deprecated
@Deprecated
注解告诉编译器被修饰的类、方法等即将被废弃,不应该继续使用了。编译器会有一个警告⚠️
提示,/** * @deprecated * 为什么被废弃了 */ @Deprecated public void oneMethod() { }
@deprecated
用在文档中,@Deprecated
才是注解 -
@SuppressWarnings
有时候不想看到某些警告
⚠️
,就可以用这个注解。例如使用一个被废弃的方法将会产生一个警告⚠️
,可以用@SuppressWarnings
抑制警告,让警告⚠️
不显示。@SuppressWarnings("deprecation") void myMethod() { myObject.deprecatedMethod(); }
自定义注解
自定义注解的定义和定义接口比较类似,因为他的定义以@interface
开头。
先看一个例子,然后一点点解释相关知识。
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Target(value={ElementType.METHOD})
@Inherited
@Retention(RetentionPolicy.SOURCE)
public @interface MyCustomAnnotation { // 只有 public 或者 abstract 可以修饰注解
int age() default 18; // 默认是public
String name();
String address();
String[] hobbies();
}
-
注解可以有一些元素,如上例中的
String name();
。这些元素的定义和接口的定义也非常相似,但是返回需要有一个类型(包括基本数据类型、字符串、类、枚举、注解、或者前面这几种类型的数组),括号内不能有参数,且可以用default
定义默认值。元素的默认值可以在使用时不再赋值直接用默认值,而如果没有默认值的元素在使用时需要先赋值。
-
注解可以有元注解(meta annotations), 包括
@Documented
、@Target
、@Inherited
和@Retention
。-
@Documented
表示使用这个注解的元素在javadoc的文档中必须有注释。默认情况下,javadoc是不包括注解的。但如果声明注解时指定了@Documented
,则它会被javadoc之类的工具处理, 所以注解类型信息也会被包括在生成的文档中。 -
@Target
表示这个注解主要用在哪个类型上,如果不定义则能用在所有类型上。ElementType有很多类型:ElementType.TYPE // 接口、类、枚举、注解
ElementType.FIELD // 变量,枚举常量
ElementType.METHOD // 方法
ElementType.PARAMETER // 方法参数
ElementType.CONSTRUCTOR // 构造函数
ElementType.LOCAL_VARIABLE // 局部变量
ElementType.ANNOTATION_TYPE// 注解
ElementType.PACKAGE // 包
-
@Inherited
表示类使用了这个注解,子类也继承父类中的这个注解 -
@Retention
是表示注解存在的周期,RetentionPolicy也有很多类型:RetentionPolicy.SOURCE // 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
RetentionPolicy.CLASS // 注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
RetentionPolicy.RUNTIME // 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
-
内置注解的源码
-
@Override
源码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Override
没有元素,只能用在方法上,且生存的周期只存在于源码阶段
-
@Deprecated
源码
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface Deprecated {
String since() default "";
boolean forRemoval() default false;
}
@Deprecated
有两个元素:1,从哪个版本开始被废弃的(不建议使用) 2,将来是否会被移除,这两个值都有默认值,所以不需要一定赋值。这个注解能够使用在构造函数等多个类型上,且在运行时都存在。
使用方法:
@Deprecated(since="9", forRemoval=true)
or@Deprecated()
-
@SuppressWarnings
源码
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
@SuppressWarnings
有一个元素且需要外部赋值,且生存的周期只存在于源码阶段
使用方法:
@SuppressWarnings(value={"all"})
or@SuppressWarnings(value="all")
or@SuppressWarnings("all")
参考文献:
网友评论