注解
什么是注解
注解是从JDK5.0开始引入的新技术,它不是程序本身,但是可以对程序做出解释,可以通过反射机制被其他程序,比如编译器读取,一般来说,我们使用@注解名
来表示一个注解,当然其中也可以添加些参数值,比如@SuppressWarnings(value=“unchecked”)。我们可以将注解附加在package、class、method、field等上面,此时我们就相当于给他们添加了额外的辅助信息
内置注解
@Override:该注解定义在java.lang.Override中,只适用于修饰方法,表示该方法是对父类中的另一个相同方法的重写
@Deprecated:该注解定义在java.lang.Deprecated中,可以用于修饰方法、属性、类,表示不鼓励使用被该注解注解的元素,通常是因为它不安全或者已经过时
@SuppressWarnings:该注解定义在java.lang.SuppressWarnings中,可以用于抑制编译时的警告信息,但是它又于上述两个注解有所不同,它使用时需要添加参数:
参数名 | 作用 |
---|---|
deprecation | 使用了不赞成使用的类或方法时的警告 |
unchecked | 执行了未检查的转换时的警告,例如当使用集合时没有用泛型来指定集合的保存类型 |
fallthrough | 当Switch程序块直接通往下一种情况而没有break时的警告 |
path | 在类路径、源文件路径等中有不存在路径时的警告 |
serial | 当在可序列化的类上缺少serialVersionUID定义时的警告 |
finally | 任何finally子句不能正常完成时的警告 |
all | 关于以上所有情况的警告 |
元注解
元注解就是注解其他注解的注解,Java中定义了4个标准的元注解类型,分别是@Target
, @Retention
, @Documented
, @Inherited
@Target:用于描述注解的使用范围(即说明被描述的注解可以在什么地方使用,比如方法、属性之类的),该注解的参数有如下取值:
参数名 | 作用 |
---|---|
ElementType.TYPE | 表示该注解可以使用在类、接口(包括注释类型)、枚举的声明上 |
ElementType.FIELD | 表示该注解可以用在字段的声明上,包括枚举常量的声明 |
ElementType.METHOD | 表示该注解可以用在方法的声明上 |
ElementType.PARAMETER | 表示该注解可以用在形参的声明上 |
ElementType.CONSTRUCTOR | 表示该注解可以用在构造方法的声明上 |
ElementType.LOCAL_VARIABLE | 表示该注解可以用在局部变量的声明上 |
ElementType.ANNOTATION_TYPE | 表示该注解可以用在注解类型的声明上 |
ElementType.PACKAGE | 表示该注解可以用在包的声明上 |
ElementType.TYPE_PARAMETER | 表示该注解可以用在类型参数的声明上 |
ElementType.TYPE_USE | 表示该注解可以用在类型的使用上 |
@Retention:用于表示需要什么级别保存该注解信息,用于描述注解的生命周期,有三种级别:SOURCE
(注解仅保留在源文件中,当Java文件被编译成class文件时,注解会被遗弃), CLASS
(注解保留到class文件,但是JVM加载class文件时会将注解遗弃), RUNTIME
(注解不仅保存到class文件中,JVM加载class文件后,仍然存在)
@Documented:表示是否将注解生成在javadoc中
@Inherited:表示子类可以继承父类中的该注解
自定义注解
使用@interface
来自定义注解
解释下该方式的一些注意事项:
1、该写法已经自动继承了java.lang.annotation.Annotation接口
2、该接口里的每个方法实际上是声明了一个配置参数,并且方法的名称就是参数的名称,返回值的类型就是该参数的类型(返回值只能是基本类型、Class、String、enum)
3、可以使用default来声明参数的默认值
4、如果只有一个参数成员,一般参数名为value,这是因为我们在使用该注释时,书写参数可以直接省略value=
,直接写参数值,如果是其他情况的话,则必须参数名=参数值
5、注解元素必须要有值,我们定义注解元素时,经常使用空字符串、0作为默认值
下面通过代码对这些注意事项进行解释:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class Test {
// 因为我设置了注解参数的默认值为"",所以此处不写参数也不会报错,但是如果我没写参数的默认值,由于注释接口里定义了参数,所以必须得写上参数,如果没定义的话,也可以不用写
@MyAnnotation
public void test() {
}
}
@Target({
ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
// 注解的参数: 参数类型 + 参数名 + () + [default 默认值]
String value() default "";
}
如果某参数的默认值设置为-1,则可以代表该参数可能不存在
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({
ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
int value() default -1;
}
注解有多个参数时可以没有顺序,只需要用 参数名=参数值 的方式书写即可
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class Test {
@MyAnnotation(id=0, name="Warren", age=18)
public void test(){
}
}
@Target({
ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String name();
int age();
int id();
}