1.元注解:Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:
@Target
@Retention
@Documented
@Inherited
@Target
源码:
package java.lang.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();
}
作用:用于描述注解的使用范围
取值:
package java.lang.annotation;
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
}
- @Retention 源码:
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
取值:
package java.lang.annotation;
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文件中有效(即class保留)
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
}
- @Documented 源码
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
作用:用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。
- @Inherited 源码
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
作用:用于标记父类的注解被子类继承,注意,仅针对类,成员属性/方法不受此注解影响。 对于成员属性和方法来说,非重写的都会保持和父类一样的注解,而被实现的抽象方法,被重写的方法都不会有父类的注解。
2.自定义注解
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
定义注解格式:
public @interface 注解名 {定义体}
支持的数据类型:
- 所有基本数据类型(int,float,boolean,byte,double,char,long,short)
- String类型
- Class类型
- enum类型
- Annotation类型
- 以上5中类型的数组
参数定义规范:
- 只能使用public/默认(default)2中访问修饰符,例如String value();这里把方法设为default默认类型;
- 如果只有一个变量,最好设置参数名为“value”,后加小括号。
- 参数必须要有确定的值,要么指定默认值,要么在使用注解时指定,非基本数据类型的注解元素不可为null。因此,使用默认空字符串或者0作为默认值是一种常用的做法。
3.解析注解:
@Description注解:
package com.wusuiwei.annotation;
import java.lang.annotation.*;
//@Retention传参RetentionPolicy.CLASS/RetentionPolicy.SOURCE时,运行时不能获取到参数
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface Description {
String value() default "";
}
Person接口:
package com.wusuiwei.annotation;
public interface Person {
public String name();
public int age();
public void work();
}
Child类:
package com.wusuiwei.annotation;
@Description("This is an class descreption.")
public class Child implements Person {
@Override
@Description("This is an method descreption.")
public String name() {
return null;
}
@Override
public int age() {
return 0;
}
@Override
public void work() {
}
}
解析注解:
package com.wusuiwei.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class ParseAnnotation {
public static void main(String[] args) {
try {
Class<?> c= Class.forName("com.wusuiwei.annotation.Child");
boolean isExist = c.isAnnotationPresent(Description.class);
System.out.println(isExist);
if (isExist) {
Description descreption = c.getAnnotation(Description.class);
System.out.println(descreption.value());
}
Method[] ms = c.getMethods();
//第一种遍历方法
for (Method m :ms) {
boolean isExist1 = m.isAnnotationPresent(Description.class);
if (isExist1) {
Description description1= m.getAnnotation(Description.class);
System.out.println("第二种遍历方法:");
System.out.println(description1.value());
}
}
//第二种遍历方法
for (Method m : ms) {
//拿到方法上的所有的注解
Annotation[] as=m.getAnnotations();
for (Annotation a : as) {
//用二元操作符判断a是否是Description的实例
if (a instanceof Description) {
Description d=(Description) a;
System.out.println("第二种遍历方法:");
System.out.println(d.value());
}
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}