愉快地学Java语言:第十八章 注解

导读

本文适合Java入门,不太适合Java中高级软件工程师。本文以《Java核心技术》第10版为蓝本,采用不断提出问题,然后解答问题的方式来讲述。本篇文章只是这个系列中的一篇,如果你喜欢这种讲解方式,或者觉得从中能学到知识,可以关注我,以便查阅本系列其他文章。

愉快地学Java语言:第十八章 注解

让我们开始愉快地学习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元注解

元注解是可以修饰一个注解的注解。

愉快地学Java语言:第十八章 注解

@Target

看下面注解Override的实现中使用了@Target;然后我们看下@Target的实现,发现它只定义一个元素value,并且它还使用了自身。这种“注解自己修饰自己”很有意思。通过给value赋值就可以限制其可修饰的元素,譬如,@Override的@Target使用ElementType.METHOD,表明@Override只能用来修饰方法,而@Target的@Target使用ElementType.ANNOTATION_TYPE,表明其只能用来修饰注解

愉快地学Java语言:第十八章 注解

愉快地学Java语言:第十八章 注解

有必要将ElementType的每个值,因此我列了个表格

愉快地学Java语言:第十八章 注解

@Retention

看下面@Retention的定义,它只定义了一个元素value,它的返回值类型为RetentionPolicy,通过为value赋值来设置注解保留策略。

愉快地学Java语言:第十八章 注解

愉快地学Java语言:第十八章 注解

我们来写一个例子观察下,这个注解的作用

愉快地学Java语言:第十八章 注解

愉快地学Java语言:第十八章 注解

愉快地学Java语言:第十八章 注解

使用反射检测一下类AnnUsing是否使用了CustomAnn修饰,代码及执行结果如上,发现没有检测到CustomAnn,但是我已明确使用CustomAnn注解修饰AnnUsing类了,为啥调用isAnnotationPresent返回值为false呢?

如果我们在CustomAnn上添加@Retention(RetentionPolicy.RUNTIME),那么在调用isAnnotationPresent,其返回值为true

@Documented

上面对@Documented的说明比较抽象,下面我们来实践一下,看看到底会有啥现象。

愉快地学Java语言:第十八章 注解

愉快地学Java语言:第十八章 注解

让我们使用javadoc命令生成文档看看,注意选择适当的编码以防中文乱码

愉快地学Java语言:第十八章 注解

打开/home/doc/index.html,看下页面显示

愉快地学Java语言:第十八章 注解

如果将上述自定义注解中的@Documented去掉,生成文档如下

愉快地学Java语言:第十八章 注解

可以发现,使用@Documented修饰CustomAnn,那么使用CustomAnn修饰AnnUsing,生成的文档中会显示出AnnUsing这个类被CustomAnn这一注解修饰。

@Inherited

看一个例子,演示下这个注解的作用。

愉快地学Java语言:第十八章 注解

愉快地学Java语言:第十八章 注解

愉快地学Java语言:第十八章 注解

愉快地学Java语言:第十八章 注解

由上面结果可以看出子类Child也被@CustomAnn修饰,虽然我没有将@CustomAnn写在Child类上。如果将@Inherited去掉,那么isAnnotationPresent返回值为false。

4.2用于编译的注解

愉快地学Java语言:第十八章 注解

@Deprecated

定义如下,可以看出其可以应用于:

愉快地学Java语言:第十八章 注解

愉快地学Java语言:第十八章 注解

@SuppressWarnings

定义如下,可以看出其适用范围和@Deprecated差不多,只是不能用于包声明。它定义了一个元素value,代表抑制警告的类型,那么都有哪些类型呢?

愉快地学Java语言:第十八章 注解

愉快地学Java语言:第十八章 注解

注,这些关键字的英文释义参见网址:

https://help.eclipse.org/kepler/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-suppress_warnings.htm

愉快地学Java语言:第十八章 注解

@Generated

这个注解是给代码生成工具使用的,也就是说,不一定所有代码都是我们一个字符一个字符地敲上去的,也可以用代码生成工具自动生成一段代码,为了按照一定规则生成代码,我们可以使用这个注解,凡是被这个注解标注的部分都可以用代码生成工具生成。

4.3 用于管理资源的注解

愉快地学Java语言:第十八章 注解


你还可以看看往期文章:


分享到:


相關文章: