标签:
从JDK5开始,Java增加了注解(Annotation),注解是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。通过使用注解,开发人员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充的信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证、处理或者进行部署。
注解提供了一种为程序元素(包、类、构造器、方法、成员变量、参数、局域变量)设置元数据的方法。跟public、static等修饰符一样,注解是这些程序元素的属性,是这些程序元素的一部分,不能脱离程序元素使用。
如果希望注解在运行时起到作用,需要访问和处理注解的工具,这些工具统称为APT(Annotation Processing Tool)。
1 基本注解
JDK默认提供了如下几个基本注解:
@Override
限定重写父类方法。对于子类中被@Override 修饰的方法,如果存在对应的被重写的父类方法,则正确;如果不存在,则报错。@Override 只能作用于方法,不能作用于其他程序元素。
@Deprecated
用于表示某个程序元素(类、方法等)已过时。如果使用被@Deprecated修饰的类或方法等,编译器会发出警告。
@SuppressWarning
抑制编译器警告。指示被@SuppressWarning修饰的程序元素(以及该程序元素中的所有子元素,例如类以及该类中的方法.....)取消显示指定的编译器警告。例如,常见的@SuppressWarning(value="unchecked")
@SafeVarargs
@SafeVarargs是JDK 7 专门为抑制“堆污染”警告提供的。
2 元注解
为了修饰注解定义,JDK提供了如下4个元注解(注解的注解):
@Retention
@Target
@Documented
@Inherited
2.1 @Retention
@Retention修饰一个Annotation定义,用于指定被修饰的Annotation可以保留多长时间。
@Retention包含一个value成员变量,该value成员变量是RetentionPolicy枚举类型的。使用@Retention时,必须为其value指定值。
value成员变量的值只能是如下3个:
RetentionPolicy.SOURCE:注解只保留在源代码中,编译器编译时,直接丢弃这种注解。
RetentionPolicy.CLASS:编译器把注解记录在class文件中。当运行Java程序时,JVM中不再保留该注解。
RetentionPolicy.RUNTIME:编译器把注解记录在class文件中。当运行Java程序时,JVM会保留该注解,程序可以通过反射获取该注解的信息。
示例:
package com.demo1; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; //@Retention(value=RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME) public @interface AnnTest { String name() default "sunchp"; }
如果注解里有一个value成员变量,使用该注解时可以直接在注解后的括号里指定value成员变量的值,无须使用name=value形式。
2.2 @Target
@Target修饰一个注解定义,用于指定被修饰的注解能用于修饰哪些程序元素。@Target也包含一个名为value的成员变量,该成员变量的值有如下几个:
ElementType.TYPE:能修饰类、接口或枚举类型
ElementType.FIELD:能修饰成员变量
ElementType.METHOD:能修饰方法
ElementType.PARAMETER:能修饰参数
ElementType.CONSTRUCTOR:能修饰构造器
ElementType.LOCAL_VARIABLE:能修饰局部变量
ElementType.ANNOTATION_TYPE:能修饰注解
ElementType.PACKAGE:能修饰包
示例1(单个ElementType):
package com.demo1; import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target(ElementType.FIELD) public @interface AnnTest { String name() default "sunchp"; }
示例2(多个ElementType):
package com.demo1; import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target({ ElementType.FIELD, ElementType.METHOD }) public @interface AnnTest { String name() default "sunchp"; }
2.3 @Documented
@Documented用于指定被该元注解修饰的注解类定义,将被javadoc工具提取成文档。如果定义注解类A时,使用了@Documented,则所有使用该注解类A修饰的程序元素的API文档中,将会包含该注解类A的说明。
示例:
@Documented public @interface Testable { }
public class Test { @Testable public void info() { } }
2.4 @Inherited
@Inherited指定被它修饰的注解具有继承性。
示例:
package com.demo2; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Inheritedable { }
package com.demo2; @Inheritedable public class Base { }
package com.demo2; //SubClass只是继承了Base类 //并未直接使用@Inheritedable注解修饰 public class SubClass extends Base { public static void main(String[] args) { System.out.println(SubClass.class.isAnnotationPresent(Inheritedable.class)); } }
如果Inheritedable 注解被@Inherited修饰,则运行结果为:true;如果Inheritedable 注解没有被@Inherited修饰,则运行结果为:false。
3 自定义注解
4 注解与反射
5 注解本质
6 注解的意义
标签:
原文地址:http://my.oschina.net/sunchp/blog/376120