导读
本文适合Java入门,不太适合Java中高级软件工程师。本文以《Java核心技术》第10版为蓝本,采用不断提出问题,然后解答问题的方式来讲述。本篇文章只是这个系列中的一篇,如果你喜欢这种讲解方式,或者觉得从中能学到知识,可以关注我,以便查阅本系列其他文章。
让我们开始愉快地学习Java语言吧!
1注解简介
注解是什么?
从语法角度讲,注解是一种接口,而且是一种特殊的接口。
为什么说注解是一种特殊的接口,特殊在哪里?
都隐式扩展自java.lang.annotation.Annotation接口;
不能泛型化;
不能扩展注解(接口);
只能定义没有参数的方法,且方法的返回类型是有限制的,也不能定义会抛出异常的方法,方法可以有一个默认返回值。
注解有什么作用?
可以使用注解修饰类、类的成员、局部变量等,以便提供额外的信息。会提供什么样的额外信息呢?概括来讲,无法在一般程序代码中体现的信息,都可以使用注解来表达。
2注解语法
修饰符 @interface 注解名称{
类型 方法名();
...
}
1)方法可以有默认的返回值,定义形式为:
类型 方法名() default 默认值;
2)上面提到方法返回值类型是有限制的,那么什么样的类型可以作为方法返回值呢?
以下类型都可:基本类型、String、Class、枚举、注解
由上面那些类型构成的数组
3)我们称注解中定义的方法为元素。使用下面的形式,每个注解可以包含多个元素。
@注解名称(元素名称=value1,...,元素名称=value2,)
4)注解元素的顺序任意,因为是根据键值对的形式来识别注解元素的。
5)如果定义了某个元素,但是使用的时候没给他赋值,那么就使用默认值。
6)默认值不是和注解存储在一起,这有什么好处呢?
如果你修改了注解的默认值,然后重新编译,那么对于使用了这些注解的代码来说,不用重新编译这部分代码,他们也会使用修改后的默认值,所以这个默认值是动态变化的。
7)如果注解没有定义任何方法或者使用注解时元素都为默认值,可简化为:@注解名称,我们称之为标记注解,@Override就是标记注解。
8)如果一个注解只有一个方法且方法名为value,我们称之为单值注解,使用时可以简化为:@注解名称(value1)
9)使用注解时,所有元素值必须是编译期常量。
10)注解元素的默认值不能是null,使用注解时也不能给元素赋null
11)元素类型为数组,那么赋值时要使用大括号表示数组。
12)可以用多个注解修饰一个目标
13)可以多次重复使用一个注解,但前提定义注解的时候是要声明为可重复
3注解出现的位置
注解可以修饰:包、类、接口、方法、构造器、实例域、局部变量、参数变量、类型参数、枚举、枚举常量。
1)修饰类、接口、修饰方法、构造器、实例域
位于各个修饰符的最前面
2)修饰变量(局部变量、参数变量)
位于类型前
3)修饰类型参数
位于类型参数前
4 Java SE提供的注解
4.1元注解
元注解是可以修饰一个注解的注解。
@Target
看下面注解Override的实现中使用了@Target;然后我们看下@Target的实现,发现它只定义一个元素value,并且它还使用了自身。这种“注解自己修饰自己”很有意思。通过给value赋值就可以限制其可修饰的元素,譬如,@Override的@Target使用ElementType.METHOD,表明@Override只能用来修饰方法,而@Target的@Target使用ElementType.ANNOTATION_TYPE,表明其只能用来修饰注解
有必要将ElementType的每个值,因此我列了个表格
@Retention
看下面@Retention的定义,它只定义了一个元素value,它的返回值类型为RetentionPolicy,通过为value赋值来设置注解保留策略。
我们来写一个例子观察下,这个注解的作用
使用反射检测一下类AnnUsing是否使用了CustomAnn修饰,代码及执行结果如上,发现没有检测到CustomAnn,但是我已明确使用CustomAnn注解修饰AnnUsing类了,为啥调用isAnnotationPresent返回值为false呢?
如果我们在CustomAnn上添加@Retention(RetentionPolicy.RUNTIME),那么在调用isAnnotationPresent,其返回值为true
@Documented
上面对@Documented的说明比较抽象,下面我们来实践一下,看看到底会有啥现象。
让我们使用javadoc命令生成文档看看,注意选择适当的编码以防中文乱码
打开/home/doc/index.html,看下页面显示
如果将上述自定义注解中的@Documented去掉,生成文档如下
可以发现,使用@Documented修饰CustomAnn,那么使用CustomAnn修饰AnnUsing,生成的文档中会显示出AnnUsing这个类被CustomAnn这一注解修饰。
@Inherited
看一个例子,演示下这个注解的作用。
由上面结果可以看出子类Child也被@CustomAnn修饰,虽然我没有将@CustomAnn写在Child类上。如果将@Inherited去掉,那么isAnnotationPresent返回值为false。
4.2用于编译的注解
@Deprecated
定义如下,可以看出其可以应用于:
@SuppressWarnings
定义如下,可以看出其适用范围和@Deprecated差不多,只是不能用于包声明。它定义了一个元素value,代表抑制警告的类型,那么都有哪些类型呢?
注,这些关键字的英文释义参见网址:
https://help.eclipse.org/kepler/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-suppress_warnings.htm
@Generated
这个注解是给代码生成工具使用的,也就是说,不一定所有代码都是我们一个字符一个字符地敲上去的,也可以用代码生成工具自动生成一段代码,为了按照一定规则生成代码,我们可以使用这个注解,凡是被这个注解标注的部分都可以用代码生成工具生成。
4.3 用于管理资源的注解
你还可以看看往期文章:
閱讀更多 甜橙很酸 的文章