Java之基础注解(基于jdk1.8)

或许你经常使用框架,经常使用注解进行快捷开发,但是你了解注解是怎么实现的吗,本篇博客将探讨下java中的四个元注解

首先说下jdk1.8在注解方面的新特性:jdk1,8新增了重复注解与类型注解

重复注解:

在1.8以前,同一个程序元素前最多只能有一个相同类型的注解; 如果需要在同一个元素前使用多个相同类型的注解,必须要使用注解容器。

public@interfaceAuthority {
     String role();
}
public@interfaceAuthorities {     //@Authorities注解作为可以存储多个@Authority注解的容器
    Authority[] value();
}
publicclassRepeatAnnotationUseOldVersion {
    @Authorities({@Authority(role="Admin"),@Authority(role="Manager")})
    publicvoiddoSomeThing(){
   }
}

jdk1.8新增了重复注解,其使用方式为:

@Repeatable(Authorities.class)
public@interfaceAuthority {
     String role();
}
public@interfaceAuthorities {
    Authority[] value();
}
publicclassRepeatAnnotationUseNewVersion {
    @Authority(role="Admin")
    @Authority(role="Manager")
    publicvoiddoSomeThing(){ }
}

不同的地方是,创建重复注解Authority时,加上@Repeatable,指向存储注解Authorities,在使用时候,直接可以重复使用Authority注解。从上面例子看出,java 8里面做法更适合常规的思维,可读性强一点。但是,仍然需要定义容器注解。

类型注解:

Java8为ElementType枚举增加了TYPE_PARAMETER、TYPE_USE两个枚举值,从而可以使用@Target(TYPE_PARAMETER),@Target(TYPE_PARAMETER)修饰注解定义,这种注解被称为类型注解,可以用在任何使用到类型的地方。具体在下面说。

java中有四个元注解:

1. @Retention  2. @Target   3. @Document  4. @Inherited 

如何建一个注解类?  新建文件时选择Annotation文件即可

看下四个注解的源码:

1. @Retention注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

可以看到这个注解类中定义了一个RetentionPolicy方法,说明在使用retention注解时,可以在注解后面的括号里填入一个retentionPolicty实例,我们再看下retentionPolicity的源码:

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
}

可以看到这是一个枚举类,里面有三个属性,这每一个属性都代表一个枚举实例,这三个属性定义了注解的存在时间

@Retention(RetentionPolicy.SOURCE)   注解仅存在于源码中,在class类文件中不存在

@Retention(RetentionPolicy.CLASS)  默认的保留策略,注解在字节码文件中存在,但是运行时无法通过反射获得

@Retention(RetentionPolicy.RUNTIME) 注解在class文件中存在,在运行时可以通过反射获得

2.@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注解里面有一个ElementType数组,也就是说Target注解后可以定义多个ElementType对象,这个对象决定了@Target注解可以定义再哪个位置,再去看下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
}

一 一解释下里面属性的含义:

@Target(ElementType.TYPE)  注解可以定义在接口、类、枚举、注解上

@Target(ElementType.FIELD) 注解可以定义在字段、枚举的常量

@Target(ElementType.METHOD) 注解可以定义在方法上

@Target(ElementType.PARAMETER) 注解可以定义在方法参数上

@Target(ElementType.CONSTRUCTOR) 注解可以定义在构造方法上

@Target(ElementType.LOCAL_VARIABLE) 注解可以定义在局部变量上

@Target(ElementType.ANNOTATION_TYPE) 注解可以定义在注解上

@Target(ElementType.PACKAGE)  注解可以声明在包上

还有两个JDK1.8新增的类型:

@Target(ElementType.TYPE.PARAMETER)  用于类型参数声明语句,这里可能大家不明白类型参数是什么,所以举个例子:

@Target(ElementType.TYPE_PARAMETER)
public @interface NotNull {
}

class MyBox <@NotNull T, @NotNull S> {
    private T t;
    private S s;
 
    public void add(T t, S s) {
        this.t = t;
        this.s = s;
    }
 
    public T getFirst() {
        return t;
    }
 
    public S getSecond() {
        return s;
    }
}

@Target(ElementType.TYPE_USE)  表示注解可以在任何用到类型的地方使用,比如以下位置:

 1. 创建对象(用new关键字创建)
 2. 类型转换
 3. 使用implements实现接口
 4.使用throws声明抛出异常

@Target(ElementType.TYPE_USE)
@interface NotNull{ }
//定义类时使用
@NotNull
public class TypeAnnotationTest  implements Serializable    //在implements时使用
{
    //在方法形参中使用
 public static void main(@NotNull String [] args)  throws @NotNull  FileNotFoundException //在throws时使用
 {
       Object  obj="fkjava.org";
  //使用强制类型转换时使用
       String str=(@NotNull String) obj;
         //创建对象时使用
       Object win=new (@NotNull) JFrame("疯狂软件");   
 } 
  //泛型中使用
 public void foo(List<@NotNull String> info)  { }
}

3.@Document注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

拥有这个注解的元素可以被javadoc此类的工具文档化。它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。相当与@return,@param 等。

4.@Inherited注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

定义注解类A,A中使用@Inherited,在B中使用注解A,C继承B,C可以继承B中使用的注解A

最后送大家一段苹果的广告语,致疯狂的人

      他们特立独行。他们桀骜不驯。他们惹是生非。他们格格不入。他们用与众不同的眼光看待事物。他们不喜欢墨守成规。他们也不愿安于现状。你可以认同他们,反对他们,颂扬或是诋毁他们。但唯独不能漠视他们。因为他们改变了寻常事物。他们推动人类向前迈进。或许他们是别人眼里的疯子,但他们却是我们眼中的天才。因为只有那些疯狂到以为自己能够改变世界的人,才能真正改变世界。

猜你喜欢

转载自blog.csdn.net/qq_37113604/article/details/81974482