什么是注解
简单的说注解是jdk1.5开始的一种用在源码上的一个标记,这个标记以@开头,可以用在类、字段、方法上面并且它们不会改变原有程序的运行。这些信息可以在开发和部署时期让很多工具使用,也可以通过编程方式动态的获取并使用注解提供的功能。
注解分类
- 元注解 元注解是用来定义用户注解的注解
- 用户注解 可以简单理解为除了元注解外的所有注解
java的元注解在 java.lang.annotation 包下面:
- @Documented 简单的说就是这个注解的注释是否出现在使用该注解的javadoc里面。
- @Retention 保留策略,目前仅三种:SOURCE、CLASS、RUNTIME
- @Target 指定该注解可以在哪里使用。比如类、方法、字段,也可以是其中的组合。具体参考 ElementType
- @Inherited 标记该注解是否会被继承,如果A使用了注解@Test,B继承A,@Test注解有@Inherite,则B能获取到A的注解,反之获取不到该注解
三种元注解的详细使用与例子
1、有无@Documented生成的javadoc举例
/** java注解基础 */
public class AnoTest {
/** 这是一个测试注解 @author 大灰狼 */
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
}
/** 测试【Test注解】 */
@Test
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestForAno {
}
}
以上代码生成的javadoc如下截图:
下面我们去掉@Documented注解
/** java注解基础 */
public class AnoTest {
/** 这是一个测试注解 @author 大灰狼 */
// @Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
}
/** 测试【Test注解】 */
@Test
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestForAno {
}
}
注释掉@Documented代码生成的javadoc如下截图:
2、@Retention 保留策略的区别
SOURC保留策略,测试代码如下
/** java注解基础 */
@Test
public class AnoTest {
/** 这是一个测试注解 @author 大灰狼 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Test {
String info() default "defaultVal";
}
// 测试@Retention不同保留策略
public static void main(String[] args) {
Annotation[] ans = AnoTest.class.getAnnotations();
System.out.println("注解数量:" + ans.length + ",第一个注解:" + (ans.length == 0 ? null : ans[0]));
}
}
输出结果如下:
注解数量:0,第一个注解:null
通过JD_GUI反编译工具代码如下,类上面的注解已经不见了:
CLASS保留策略,测试代码如下
/** java注解基础 */
@Test
public class AnoTest {
/** 这是一个测试注解 @author 大灰狼 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface Test {
String info() default "defaultVal";
}
// 测试@Retention不同保留策略
public static void main(String[] args) {
Annotation[] ans = AnoTest.class.getAnnotations();
System.out.println("注解数量:" + ans.length + ",第一个注解:" + (ans.length == 0 ? null : ans[0]));
}
}
输出结果如下:
注解数量:0,第一个注解:null
通过JD_GUI反编译工具代码如下,类上面的注解还在,但是代码中已经获取不到:
RUNTIME保留策略,测试代码如下
/** java注解基础 */
@Test
public class AnoTest {
/** 这是一个测试注解 @author 大灰狼 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
String info() default "defaultVal";
}
// 测试@Retention不同保留策略
public static void main(String[] args) {
Annotation[] ans = AnoTest.class.getAnnotations();
System.out.println("注解数量:" + ans.length + ",第一个注解:" + (ans.length == 0 ? null : ans[0]));
}
}
输出结果如下:
注解数量:1,第一个注解:@sp.AnoTest$Test(info=defaultVal)
从上面的例子可以看出: 我们通过代码只能获取到RUNTIME保留策略的注解,这是为什么呢?下面我们来看看保留策略的原始说明:
/** Annotations are to be discarded by the compiler. */
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler but need not be
* retained by the VM at run time. This is the default behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*/
RUNTIME
SOURCE: 在编译阶段就丢弃了注解,也就是说只有源码里面能看到,比如我们@Override注解
CLASS: 保留在编译后的Class文件面,但是运行时虚拟机不会去获取他,而且这个是默认保留策略,也就是说这个注解是在编译时候使用的,比如可以在编译期动态生成一些源码等等。比如:Lombok工具的@NonNull注解
RUNTIME:保留在编译后的Class文件里面,并且虚拟机在运行时动态获取,这也是使用的最频繁的策略。
3、@Target 使用如下
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
上面是java自带的@Documented注解,@Target值可以是以下列表中的任意一个或者其组合,如果注解用在不匹配的的类型上会直接抛出check异常:
- TYPE,
- FIELD,
- METHOD,
- PARAMETER,
- CONSTRUCTOR,
- LOCAL_VARIABLE,
- ANNOTATION_TYPE,
- PACKAGE,
- TYPE_PARAMETER,
- TYPE_USE
以上就是对三个元注解的详细解释。 下一篇文章我们将讲解从xml初始化java对象和对象的单例与多例