Java自定义注解Annotation

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 Java自定义注解Annotation,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、注解(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

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!