java注解是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
java注解可用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。注解是以‘@注解名’在代码中存在的,根据注解参数的个数,注解可以分为:标记注解、单值注解、完整注解三类。它们都不会直接影响到程序的语义,只是作为注解(标识)存在,我们可以通过反射实现对这些注解的访问。另外,也可以在编译时选择代码里的注解是否只存在于源代码级,或者它也能在class文件、或者运行时中出现。
基本内置注解
@Override
这个注解比较常见,它是对覆盖超类中方法的方法进行标记,如果被标记的方法并没有实际覆盖超类中的方法,则编译器会发出错误警告。
@Deprecated
这个注解表示方法过时,建议使用其他方法代替。
@SuppressWarnings
这个注解表示压制警告,对方法中的警告进行屏蔽,它可以带参数,具体的参数有:
deprecation,使用了过时的类或方法时的警告
unchecked,执行了未检查的转换时的警告
fallthrough,当 switch 程序块直接通往下一种情况而没有 break 时的警告
path,在类路径、源文件路径等中有不存在的路径时的警告
serial,当在可序列化的类上缺少serialVersionUID 定义时的警告
finally ,任何 finally 子句不能正常完成时的警告
all,关于以上所有情况的警告
自定义注解
我们除了使用内置的注解外,更多情况下我们会使用自定义注解。
首先来看一下如何创建自定义注解:
1 | @Documented |
创建自定义注解与编写接口很相似,它的接口关键字前有个@符号。同时,我们也会使用元注解对其进行相应的设置。这里我们可以看到四个元注解,现在我们先来看看这四个元注解的用法:
@Documented
@Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。
@Inherited
@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于class的子类。
@Target
@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。
ElementType.CONSTRUCTOR 作用于构造器
ElementType.FIELD 作用于域/属性
ElementType.LOCAL_VARIABLE 用于描述局部变量
ElementType.METHOD 作用于方法
ElementType.PACKAGE 用于描述包
ElementType.PARAMETER 用于描述参数
ElementType.TYPE 用于描述类、接口(包括注解类型) 或enum声明。
多个声明是使用实例:@Target({ ElementType.TYPE, ElementType.METHOD})
Retention
定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。
RetentionPolicy.RUNTIME 注解会在class字节码文件中存在,在运行时可以通过反射获取到
RetentionPolicy.CLASS 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
RetentionPolicy.SOURCE 注解仅存在于源码中,在class字节码文件中不包含
而在使用注解时,还有几点要注意:首先注解方法不能有参数但是可以有默认值;其次,注解方法的返回类型局限于原始类型,字符串,枚举,注解,或以上类型构成的数组。
最后在使用注解时:
1 | @DefaultName(name="lee") |
获取注解
获取注解需要使用Java反射机制,同时注解保持性策略应该是RUNTIME,否则它的信息在运行期无效,我们也不能从中获取任何数据。
具体的代码为:
1 | Annotation annotation=method.getAnnotation(DefaultName.class); |
这个一部分在java反射部分做详细的介绍。