文章目录
- 注解
- 1.引言
- 2.分类
- 3.标准注解
- 4.元注解
- 4.1注解基本格式
- 4.2Documented
- 4.3Retention
- 4.4Target
- 4.5lnherited
- 5.自定义注解
注解
1.引言
注解是java在1.5版本后引入的一种概念,是一个非常重要的知识点,相信很多人学到这的时候都是一脸懵逼。别急,听我慢慢分析。
我们可以把注解理解成一种标签,注解能够存在的地方很多,比如在类上面,方法上【Override】,甚至在注解上也可以存在注解。那么注解有什么用呢?
首先,注解可以编译检查代码,比如@FunctionInterface开启函数式接口检查,@Override重写检查,这两个还是比较常见的,然而注解的功能远不这些,接着往下看。
2.分类
java注解可以简单分为三类:
标准注解:
@Override @FunctionalInterface @SuppressWarnings
元注解:
@Documented
@Retention
@Target
@Inherited
自定义注解
其中标准注解还是很常见的,我们先介绍一下这个。
3.标准注解
此类注解都是java定义好的注解,一般用于开始代码编译检查,例如:
@Override
开启重写检查。如果试图用@Override标记一个没有重写父类方法的方法,编译器会报警。
@FunctionalInterface
这个同理,开启函数式接口严格检查。
4.元注解
4.1注解基本格式
看元注解之前,我们先来看一下,注解的基本格式:
public @Interface AnnotationName{
//属性
//建议,属性必须有一个value属性,属性对应的数据类型不限制
}
例如:Target注解源码
//元注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
可以看到,注解和接口的声明格式很像,直接使用@Interface修饰,至于为什么建议必须有一个value呢,接下来将自定义注解我会讲到,还有在注解声明上面的注解就是元注解,那么元注解都有什么呢?
元注解是一种基本注解,它可以用到其他注解上,可以这样理解,它是一种特殊的标签,是对其他注解进行解释说明的。那么元注解最常用的有三种,我们分别来看看。
4.2Documented
@Documented
这个注解功能比较简单,就是标记当前注解参与Javadoc操作,可以生成对应的【JavaDoc文档】
4.3Retention
@Retention
该注解标记了当前注解在哪一级别可用。分别有代码编译阶段,生成.class文件阶段,代码运行阶段。这三个阶段对应了Retention的三个属性。
RetentionPolicy.SOURCE
标记当前注解只存在代码中,编译时被丢弃,不存在类文件中
RetentionPolicy.CLASS
标记当前注解在类文件中存在,但是不参与代码的运行。
RetentionPolicy.RUNTIME
标记当前代码不仅在类文件中存在,而且参与代码的运行。我们可以通过反射的方式获取对应的注解信息。
4.4Target
@target
决定当前注解可以作用于java代码中的哪一部分内容,通过枚举ElementedType来决定当期注解可以使用范围。
- ElementType.TYPE:表示注解可以用于类、接口、枚举
- ElementType.FIELD:表示注解可以用于成员变量
- ElementType.METHOD:表示注解可以用于方法
- ElementType.PARAMTER:表示注解可以用于参数
- ElementType.CONSTRUCTOR:表示注解可以用于构造器
- ElementType.ANNOTATION_TYPE:表示注解可以用于注解
- ElementType.LOCAL_VARIABLE:表示注解可以用于局部变量
- ElementType.PACKAGE:表示注解可以用于包
例如,上面的@Target注解源码,上面@Target(ElementType.ANNOTATION_TYPE)
就是标记当前注解可以用于注解之上。
4.5lnherited
@lnherited
标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
这个注解不是很常用,所以在此就不详细介绍了。
5.自定义注解
java的骚操作之一。
//自定义注解的格式
public @interface 注解名{
//注解内容,属性
}
实际代码演示:
//可以生成JavaDOC文档
@Documented
//参与到程序的运行
@Retention(RetentionPolicy.RUNTIME)
//当前注解可以用在类、接口、枚举之上
@Target(ElementType.TYPE)
public @interface Annotation {
//注解中如果用到了属性,属性列表中必须有一个value反馈类型任意
/**
* 当前注解名为value
*
* @return 反馈类型是String
*/
String value() default "";
/**
* 当前注解名为num
*
* @return 反馈类型是int
*/
int num();
}
注解里支持的类型有很多,上面只列举了基本类型和String。它支持所有的基本类型枚举,注解,还有以上所有类型的数组。
注解里使用枚举
先定义一个枚举类型,里面定义周一到周末
//枚举类型,使用关键字enum,定义周一到周末,用逗号隔开
enum Day {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
注解里面加入其他注解
再定义一个注解
public @interface MyAnnotation {
int value() default 0;
String name() default "";
}
将枚举类型和自定义注解@MyAnnotation添加进自定义注解@Annotation
public @interface Annotation {
//注解中如果用到了属性,属性列表中必须有一个value反馈类型任意
/**
* 当前注解名为value
*
* @return 反馈类型是String
*/
String value() default "";
/**
* 当前注解名为num
*
* @return 反馈类型是int
*/
int num();
/**
* 获取日期
*
* @return 反馈类型是枚举
*/
Day getDay();
/**
* 获取自定义注解的值
*
* @return 反馈类型是在自定义注解
*/
MyAnnotation[] ANNOTATIONS();
}
接下来测试,用反射的方法获取注解属性。
@Annotation(value = "注解",
num = 22,
getDay = Day.SATURDAY,
ANNOTATIONS = {
@MyAnnotation(value = 1, name = "李星云"),
@MyAnnotation(value = 2, name = "不良帅")
}
)
public class Demo {
public static void main(String[] args) {
//获取类对象
Class<Demo> cls = Demo.class;
//获取注解对象
Annotation annotation = cls.getAnnotation(Annotation.class);
//获取注解中的属性
System.out.println(annotation.num());
//获取注解中的注解属性
System.out.println(annotation.ANNOTATIONS()[0].name());
System.out.println(annotation.ANNOTATIONS()[1].name());
}
}
注解的属性赋值就是属性名 = 具体值,注解中的属性有一句话总结它的特性,我觉得很不错,最后分享给各位:
以方法之式,行变量之实,实则为方法。
怎么理解呢,我们可以看出来属性定义的时候,都带有小括号(),是方法的形式,
但是在上面赋值的时候,跟变量的赋值是一样的。很有意思,但是实际上还是方法。