参考:java
- 秒懂,Java 注解 (Annotation)你能够这样学
- 疯狂java讲义
同 classs
和 interface
同样,注解也属于一种类型。
注解经过 @interface
关键字进行定义。数组
public @interface TestAnnotation { }
默认状况下,Annotation可用于修饰任何程序元素,包括接口、类、方法等。app
Annotation成员变量
以方法形式定义Annotation中的成员变量以无形参的方法形式来声明。定义了几个成员变量,在使用时必须给值。ide
public @interface MyTag { String name(); int age(); }
有个默认值,在使用时能够不给值。工具
public @interface MyTag { String name() default "hobe"; int age() default 18; }
Annotation
jdk除了java.lang下的5个基本Annotation:.net
以外,java.lang.annotation
包下提供了6个Meta Annotation
(元Annotation),其中5个都用于修饰其余Annotation
。主要几个以下:code
只能修饰Annotation定义,指定修饰多长时间,其源码:orm
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Retention { /** * Returns the retention policy. * @return the retention policy */ RetentionPolicy value(); }
其中只有一个成员变量。blog
public enum RetentionPolicy { /** * 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. * * @see java.lang.reflect.AnnotatedElement */ RUNTIME }
SOURCE
:用于检查代码,编译时丢掉。(主要看IDE是否报错)CLASS
:(默认)。编译后也会记录在class文件中。运行时,JVM不可获取Annotation信息,不可反射获取。RUNTIME
:(一般会使用)。编译后也会记录在class文件中。运行时,JVM可获取Annotation信息,可反射获取。接口
使用示例:
@Retention(RetentionPolicy.RUNTIME) public @interface MyTag { ... }
或:
@Retention(value = RetentionPolicy.RUNTIME) public @interface MyTag { ... }
说明:
当Annotation成员变量名为value
时,只需为value指定值时, 能够在括号里直接写出value的值,无需name=value
的形式。
只能修饰Annotation定义。指定哪些程序单元能够使用,源码:
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Target { /** * Returns an array of the kinds of elements an annotation type * can be applied to. * @return an array of the kinds of elements an annotation type * can be applied to */ ElementType[] value(); }
public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ TYPE, /** Field declaration (includes enum constants) */ FIELD, /** Method declaration */ METHOD, /** Formal parameter declaration */ PARAMETER, /** Constructor declaration */ CONSTRUCTOR, /** Local variable declaration */ LOCAL_VARIABLE, /** Annotation type declaration */ ANNOTATION_TYPE, /** Package declaration */ PACKAGE, /** * Type parameter declaration * * @since 1.8 */ TYPE_PARAMETER, /** * Use of a type * * @since 1.8 */ TYPE_USE }
如只能修饰成员变量则使用:
@Target({ElementType.FIELD})
被该Annotation修饰的类将会被javadoc工具提取成文档。
被@Inherited修饰的注解,用于父类时,子类自动会加该注解。
System.out.println(ChildClass.class.isAnnotationPresent(MyTag.class));
为true
。
Annotation
标记Annotation
和元数据Annotation
根据Annotation是否包含成员变量,将其分为两类:
注意的一种状况是一个注解没有任何属性。好比
public @interface Perform {}
那么在应用这个注解的时候,括号均可以省略。
@Perform public void testMethod(){}
示例:
@Target({ElementType.FIELD}) @Retention(value = RetentionPolicy.RUNTIME) public @interface MyTag { String name() default "hobe"; //字符串 int age() default 18; //int String[] likes(); // 数组 Sex sex(); //枚举 }
使用Annotation修饰了类、方法、成员变量等成员以后,这些Annotation并不会本身生效。必须由开发者提取信息并处理。
java.lang.reflect增长了读取运行时Annotation的能力。如:
如获取Mytag注解中info方法上的全部注解,则:
Class.forName("MyTag").getMethods("info").getAnnotations()
@Target({ElementType.FIELD,ElementType.TYPE}) @Retention(value = RetentionPolicy.RUNTIME) public @interface MyTag { String name() default "hobe"; //字符串 int age() default 18; //int String[] likes(); // 数组 Sex sex() default Sex.BOY; //枚举 }
public enum Sex { BOY,GIRL }
@MyTag(likes = {"code","ball"}) public class Demo { private String name; private Integer age; private String[] likes; private Sex sex; public static void main(String[] args) { Demo demo = new Demo(); /** 仅仅注解,并不能将值赋给Demo的字段 */ System.out.println(demo); boolean hasAnnotation = Demo.class.isAnnotationPresent(MyTag.class); if (hasAnnotation){ MyTag myTag = Demo.class.getAnnotation(MyTag.class); System.out.println(myTag.name()); System.out.println(myTag.likes()); System.out.println(myTag.sex()); System.out.println(myTag.age()); } } ... }
结果:
Demo{name='null', age=null, likes=null, sex=null} hobe [Ljava.lang.String;@4617c264 BOY 18
参考:
- 秒懂,Java 注解 (Annotation)你能够这样学
- 疯狂java讲义