Java自定义注解Annotation
一、注解(Annotation)概述
注解是放在Java源码的类、方法、字段、参数前的一种特殊“注释”。
注释会被编译器直接忽略,注解则可以被编译器打包进入class文件,因此,注解是一种用作标注的“元数据”。
Java从JDK5.0开始便提供了四个meta-annotation用于自定义注解的时候使用,这四个注解为:@Target,@Retention,@Documented 和@Inherited。
二、元注解
元注解是给注解进行注解,或者说注解可以修饰其他注解,可以理解为注解的注解就是元注解。
@Documented
是一个标记注解,木有成员,用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
@Target
最常用的元注解是@Target。@Target用于描述注解的使用范围(即:被描述的注解能够被应用于源码的哪些位置):
@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();
}
@Target 注解只有唯一成员value,类型为ElementType数组。ElementType可取的值有:
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
}
TYPE:用于描述类、接口(包括注解类型) 或enum声明
FIELD:用于描述成员变量
METHOD:用于描述方法
PARAMETER:用于描述参数
CONSTRUCTOR:用于描述构造器
LOCAL_VARIABLE:用于描述局部变量
ANNOTATION_TYPE:注释类型声明
PACKAGE:用于描述包
@Retention
指定被描述的注解在什么范围内有效,即定义了Annotation的生命周期。
如果@Retention不存在,则该Annotation默认为CLASS。因为通常我们自定义的Annotation都是RUNTIME
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
RetentionPolicy可取的值
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:在源文件中有效(即源文件保留);
CLASS:在class文件中有效(即class保留);
RUNTIME:在运行时有效(即运行时保留)。
@Inherited
使用@Inherited定义子类是否可继承父类定义的Annotation。@Inherited仅针对@Target(ElementType.TYPE)类型的annotation有效,并且仅针对class的继承,对interface的继承无效
某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。类A被@Inherited标注 , 类B继承类A , 则类B默认也定义了该注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
三、定义Annotation
用@interface定义注解
public @interface CustomAnnotation {
}
定义参数、默认值 ,核心参数使用value名称
public @interface CustomAnnotation {
String name() default "";
String description() default "";
}
用元注解配置注解
必须设置@Target来指定Annotation可以应用的范围
应当设置@Retention(RetentionPolicy.RUNTIME)便于运行期读取该Annotation
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {
String name() default "";
String description() default "";
}
使用注解
@CustomAnnotation(name = "Student",description="这是Student类")
public class Student implements Serializable{
@CustomAnnotation(name = "name",description="这是name属性")
private String name;
@CustomAnnotation(name = "getName",description = "获取name属性")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
处理注解
public static void main(String[] args) {
Class<Student> aClass = Student.class;
//是否被@CustomAnnotation标注
if (aClass.isAnnotationPresent(CustomAnnotation.class)) {
//获取@CustomAnnotation注解对象
CustomAnnotation annotation = aClass.getAnnotation(CustomAnnotation.class);
// 获取@CustomAnnotation注解所对应的方法与值
try {
Method method1 = CustomAnnotation.class.getMethod("name");
String name = (String) method1.invoke(annotation);
System.out.println(name);
Method method2 = CustomAnnotation.class.getMethod("description");
String description = (String) method2.invoke(annotation);
System.out.println(description);
} catch (Exception e) {
e.printStackTrace();
}
}
Method[] methods = aClass.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(CustomAnnotation.class)) {
CustomAnnotation annotation = method.getAnnotation(CustomAnnotation.class);
System.out.println(annotation.name());
System.out.println(annotation.description());
}
}
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
if (declaredField.isAnnotationPresent(CustomAnnotation.class)) {
CustomAnnotation annotation = declaredField.getAnnotation(CustomAnnotation.class);
System.out.println(annotation.name());
System.out.println(annotation.description());
String type = null;
// 判断类型
if (int.class.isAssignableFrom(declaredField.getType()) || Integer.class.isAssignableFrom(declaredField.getType())) {
type = "Integer";
} else if (String.class.isAssignableFrom(declaredField.getType())) {
type = "String";
}
System.out.println(type);
}
}
}
注意事项
Annotation的成员定义必须满足以下三点:
成员只能用public或默认(default)这两个访问权修饰;
成员的类型只能是基本类型,String,Enum,Class,Annotation以及它们的数组类型;
如果只有一个成员,最好将其名称设为value。
常用注解方法
<T extends Annotation> T getAnnotation(Class<T> annotationType) // 根据annotationType获取注解对象
Annotation[] getAnnotations() // 获取所有注解
boolean isAnnotationPresent(Class<T> annotationType) // 判断当前元素是否被annotationType注解
Annotation[] getDeclareAnnotations() // 与getAnnotations() 类似,但是不包括父类中被Inherited修饰的注解
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/137051.html