Java元注解

文章详细介绍了Java中的元注解,包括@Documented用于控制JavaDoc是否显示注解,@Target指定注解的使用范围,@Retention定义注解的生命周期,@Inherited允许子类继承父类的注解,以及@Repeatable支持注解重复使用。这些元注解帮助开发者更好地管理和使用自定义注解。
摘要由CSDN通过智能技术生成

一、元注解

一、@Documented

1java.lang.annotation.Documented		在生成JavaDoc的时候,会将该注解显示出来。

@Document 是 java 在生成文档,是否显示注解的开关。如果一个注解@B,被@Documented标注,那么被@B修饰的类,生成文档时,会显示@B。如果@B没有被@Documented标注,最终生成的文档中就不会显示@B
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

二、@Target

一、@Target的用法

1java.lang.annotation.Target	用于设定注解使用范围
2java.lang.annotation.ElementType	Target通过ElementType来指定注解可使用范围的枚举集合
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();
}

二、ElementType的用法

	ElementType. PACKAGE。它并不是使用在一般的类中,而是用在固定的文件package-info.java中。这里需要强调命名一定是“package-info”。由于package-info.java并不是一个合法的类,使用eclipse创建类的方式会提示不合法,所以需要以创建文件的方式来创建package-info.java。
	注解只能在ElementType设定的范围内使用,否则将会编译报错。例如:范围只包含ElementType.METHOD ,则表明该注解只能使用在类的方法上,超出使用范围将编译异常。
取值注解使用范围
TYPE可用于类或者接口上
FIELD可用于域上
METHOD可用于方法上
PARAMETER可用于参数上
CONSTRUCTOR可用于构造方法上
LOCAL_VARIABLE可用于局部变量上
ANNOTATION_TYPE可用于注解类型上(被@interface修饰的类型)
PACKAGE用于记录java文件的package信息
TYPE_PARAMETER@since 1.8 可用于泛型参数/类型变量的声明语句中
TYPE_USE@since 1.8 可用于类型声明和类型参数声明(eg:声明语句、泛型和强制转换语句的类型)
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 */
    /** 可用于包上,用于记录Java文件的package信息 */
    PACKAGE,
    /**
     * Type parameter declaration
     * 可用于泛型参数
     * @since 1.8
     */
    TYPE_PARAMETER,
    /**
     * Use of a type
     * 用于类型声明和类型参数声明
     * @since 1.8
     */
    TYPE_USE
}

三、@Retention

一、@Retention的用法

1java.lang.annotation.Retention	用来标识这个注解将如何保留。
2java.lang.annotation.RetentionPolicy 	Retention通过RetentionPolicy来标识这个注解将如何保留。

@Retention修饰注解,用来表示注解的生命周期,生命周期的长短取决于@Retention的属性RetentionPolicy指定的值
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     * 返回注解的保留策略
     * @return 保留策略
     */
    RetentionPolicy value();
}

二、RetentionPolicy的用法

	三种类型生命周期:     SOURCE             <CLASS         <RUNTIME,使用RUNTIME会包含前面两个生命周期,
	分别对应于:	   Java源文件(.java文件) ---> .class文件 ---> 内存中的字节码。
注解按生命周期来划分可分为3类:
1RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
2RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
3RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
        
那怎么来选择合适的注解生命周期呢?
	首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要 在编译时进行一些预处理操作,比如生成一些辅助代码(如ButterKnife),就用 CLASS注解;如果 只是做一些检查性的操作,比如 @Override@SuppressWarnings,则 可选用 SOURCE 注解。
注:	
注解@Override用在方法上,当我们想重写一个方法时,在方法上加@Override,当我们方法的名字出错时,编译器就会报错
注解@Deprecated,用来表示某个类或属性或方法已经过时,不想别人再用时,在属性和方法上用@Deprecated修饰
注解@SuppressWarnings用来压制程序中出来的警告,比如在没有用泛型或是方法已经过时的时候
取值描述作用范围使用场景
RetentionPolicy.SOURCE表示注解只保留在源文件,当java文件编译成class文件,就会消失源文件只是做一些检查性的操作,,比如 @Override 和 @SuppressWarning
RetentionPolicy.CLASS注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期class文件(默认)要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife)
RetentionPolicy.RUNTIME注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在运行时也存在需要在运行时去动态获取注解信息
package java.lang.annotation;
/**
 * 注解保留策略。
 * 与@Retention元注解一起使用,指定注解要保留多长时间
 */
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.
     * 注解由编译器记录在类文件中,但在JVM将被忽略。
     */
    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
     * 注解由编译器记录在类文件中并且在JVM在运行时保留,因此可以通过反射读取。
     */
    RUNTIME
}

四、@Inherited

1java.lang.annotation.Inherited	该注解作用于某父类时,该注解会被父类的子类继承。
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

五、@Repeatable

1java.lang.annotation.Repeatable	
@Repeatable用于声明其它类型注解的元注解,来表示这个声明的注解是可重复的
@Repeatable的值是另一个注解,其可以通过这个另一个注解的值来包含这个可重复的注解。
    
注: 
@Repeatable 所声明的注解,其元注解@Target的使用范围要比@Repeatable的值声明的注解中的@Target的范围要大或相同,否则编译器错误,显示@Repeatable值所声明的注解的元注解@Target不是@Repeatable声明的注解的@Target的子集
@Repeatable注解声明的注解的元注解@Retention的周期要比@Repeatable的值指向的注解的@Retention得周期要小或相同。
 
注:
1、在需要重复使用的注解上修饰 @Repeatable
2@Repeatable中的参数为被修饰注解的容器的类对象(class对象)
3、容器包含一个value方法,返回一个被修饰注解的数组
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {
    /**
     * Indicates the <em>containing annotation type</em> for the
     * repeatable annotation type.
     * @return the containing annotation type
     */
    Class<? extends Annotation> value();
}
package java.lang.annotation;
public interface Annotation {
    /**
     * Returns true if the specified object represents an annotation
     * that is logically equivalent to this one.  In other words,
     * returns true if the specified object is an instance of the same
     * annotation type as this instance, all of whose members are equal
     * to the corresponding member of this annotation, as defined below:
     * <ul>
     *    <li>Two corresponding primitive typed members whose values are
     *    <tt>x</tt> and <tt>y</tt> are considered equal if <tt>x == y</tt>,
     *    unless their type is <tt>float</tt> or <tt>double</tt>.
     *
     *    <li>Two corresponding <tt>float</tt> members whose values
     *    are <tt>x</tt> and <tt>y</tt> are considered equal if
     *    <tt>Float.valueOf(x).equals(Float.valueOf(y))</tt>.
     *    (Unlike the <tt>==</tt> operator, NaN is considered equal
     *    to itself, and <tt>0.0f</tt> unequal to <tt>-0.0f</tt>.)
     *
     *    <li>Two corresponding <tt>double</tt> members whose values
     *    are <tt>x</tt> and <tt>y</tt> are considered equal if
     *    <tt>Double.valueOf(x).equals(Double.valueOf(y))</tt>.
     *    (Unlike the <tt>==</tt> operator, NaN is considered equal
     *    to itself, and <tt>0.0</tt> unequal to <tt>-0.0</tt>.)
     *
     *    <li>Two corresponding <tt>String</tt>, <tt>Class</tt>, enum, or
     *    annotation typed members whose values are <tt>x</tt> and <tt>y</tt>
     *    are considered equal if <tt>x.equals(y)</tt>.  (Note that this
     *    definition is recursive for annotation typed members.)
     *
     *    <li>Two corresponding array typed members <tt>x</tt> and <tt>y</tt>
     *    are considered equal if <tt>Arrays.equals(x, y)</tt>, for the
     *    appropriate overloading of {@link java.util.Arrays#equals}.
     * </ul>
     *
     * @return true if the specified object represents an annotation
     *     that is logically equivalent to this one, otherwise false
     */
    boolean equals(Object obj);

    /**
     * Returns the hash code of this annotation, as defined below:
     *
     * <p>The hash code of an annotation is the sum of the hash codes
     * of its members (including those with default values), as defined
     * below:
     *
     * The hash code of an annotation member is (127 times the hash code
     * of the member-name as computed by {@link String#hashCode()}) XOR
     * the hash code of the member-value, as defined below:
     *
     * <p>The hash code of a member-value depends on its type:
     * <ul>
     * <li>The hash code of a primitive value <tt><i>v</i></tt> is equal to
     *     <tt><i>WrapperType</i>.valueOf(<i>v</i>).hashCode()</tt>, where
     *     <tt><i>WrapperType</i></tt> is the wrapper type corresponding
     *     to the primitive type of <tt><i>v</i></tt> ({@link Byte},
     *     {@link Character}, {@link Double}, {@link Float}, {@link Integer},
     *     {@link Long}, {@link Short}, or {@link Boolean}).
     *
     * <li>The hash code of a string, enum, class, or annotation member-value
     I     <tt><i>v</i></tt> is computed as by calling
     *     <tt><i>v</i>.hashCode()</tt>.  (In the case of annotation
     *     member values, this is a recursive definition.)
     *
     * <li>The hash code of an array member-value is computed by calling
     *     the appropriate overloading of
     *     {@link java.util.Arrays#hashCode(long[]) Arrays.hashCode}
     *     on the value.  (There is one overloading for each primitive
     *     type, and one for object reference types.)
     * </ul>
     *
     * @return the hash code of this annotation
     */
    int hashCode();

    /**
     * Returns a string representation of this annotation.  The details
     * of the representation are implementation-dependent, but the following
     * may be regarded as typical:
     * <pre>
     *   &#064;com.acme.util.Name(first=Alfred, middle=E., last=Neuman)
     * </pre>
     *
     * @return a string representation of this annotation
     */
    String toString();

    /**
     * Returns the annotation type of this annotation.
     * @return the annotation type of this annotation
     */
    Class<? extends Annotation> annotationType();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jin-进

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值