天天看點

java注解一、介紹二、注解聲明三、注解使用四、預定義的注解類型五、其他參考:

目錄

一、介紹

二、注解聲明

三、注解使用

四、預定義的注解類型

4.1、被編譯器使用的注解

@Deprecated

@Override

@SuppressWarnings

4.2、用于其他注解的注解

@Retention

@Documented

@Target

@Inherited

@Repeatable

五、其他

參考:

一、介紹

注解(annotation),一種中繼資料,提供一些關于程式的資料,但不是程式的一部分,對程式的執行沒有直接的影響。

注解有三種用處:提供資訊給編譯器,指導編譯器行為;提供建構資訊給建構工具,這些工具有ant、mavent等,建構工具會根據這些注解産生源碼或其他檔案;運作時提供資訊,可以通過反射來獲得這些注解資訊。

定義的注解預設繼承于java.lang.annotation.Annotation接口,是以你可以繼承該注解,但是沒多大的實際用處。

二、注解聲明

@Retention(RetentionPolicy.RUNTIME)
@interface ClassPreamble {
   String author();
   String date();
   int currentRevision() default 1;
   String lastModified() default "N/A";
   String lastModifiedBy() default "N/A";
   // Note use of array
   String[] reviewers();
}
           

注解聲明與接口類似,多了個@。注解中的元素聲明與接口方法類似,元素也可以賦予預設值,通過default實作。注解的元素類型隻能是基本類型、數組、字元串、枚舉、注解、Class。定義該注解時可以被其他元注解注釋,如上面的@Retention,該注解說明自定義的注解ClassPreamble可以儲存到運作時。

三、注解使用

注解一般可以使用在類、方法、字段等java元素上,這是在定義注解時聲明的通過Target設定的。如:

@Author(
   name = "Benjamin Franklin",
   date = "3/27/2003"
)
class MyClass() { ... }
           

如果隻有一個元素,該元素名字為value的情況下,名字可以忽略:

@SuppressWarnings(value = "unchecked")
void myMethod() { ... }
可以寫成如下方式
@SuppressWarnings("unchecked")
void myMethod() { ... }
           

如果有多個元素,其他的有預設值,value元素沒有,也可以忽略其他元素,和value名字:

@MyAnnotation("aaa")
class A<T,Y>{
}
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
	public String value();
	public String name() default "";
}
           

如果沒有元素或者都有預設值,連括号也可以忽略:

@EBook
class MyClass { ... }
           

如果元素是數組,且賦予數組一個值,則不需要大括号:

@MyAnnotation("aaa")
class A<T,Y>{
}
@MyAnnotation({"bbb","ccc"})
class B{
	
}
@MyAnnotation("aaa","bbb")
class C{

}
@interface MyAnnotation{
	String[] value();
	String[] name() default "bbb";
}
           

四、預定義的注解類型

java se api中已經定義了一些注解,可以用于編譯器和用于其他注解。

4.1、被編譯器使用的注解

@Deprecated

告訴編譯器被注解的元素是被棄用的,使用會被編譯器警告。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
           

可以看出,@Deprecated可以被使用到很多地方,不局限于方法、類、字段。可以配合javadoc的@deprecated标簽使用,通過該标簽解釋下為何棄用。

// Javadoc comment follows
    /**
     * @deprecated
     * explanation of why it was deprecated
     */
    @Deprecated
    static void deprecatedMethod() { }
}
           

@Override

通知編譯器被注釋的方法必須覆寫父類方法。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
           

@SuppressWarnings

用于抑制警告

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}
           

還有其他的如@SafeVarargs、@FunctionalInterface。

4.2、用于其他注解的注解

用于注釋其他注解的注解稱為元注解。

@Retention

指定被标記的注解如何被存儲,比如存在源碼中、位元組碼中、運作時中。如果@Retention不存在,則預設使用

RetentionPolicy.CLASS政策,就是存在位元組碼中。

  • RetentionPolicy.SOURCE

     – The marked annotation is retained only in the source level and is ignored by the compiler.
  • RetentionPolicy.CLASS

     – The marked annotation is retained by the compiler at compile time, but is ignored by the Java Virtual Machine (JVM).
  • RetentionPolicy.RUNTIME

     – The marked annotation is retained by the JVM so it can be used by the runtime environment.
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}
           

@Documented

被@Document注釋的注解在其他地方被使用時,可以顯示在javadoc導出的文檔中。

java注解一、介紹二、注解聲明三、注解使用四、預定義的注解類型五、其他參考:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
           

@Target

指定注解可以使用在哪種java元素上:

  • ElementType.ANNOTATION_TYPE

     can be applied to an annotation type.
  • ElementType.CONSTRUCTOR

     can be applied to a constructor.
  • ElementType.FIELD

     can be applied to a field or property.
  • ElementType.LOCAL_VARIABLE

     can be applied to a local variable.
  • ElementType.METHOD

     can be applied to a method-level annotation.
  • ElementType.PACKAGE

     can be applied to a package declaration.
  • ElementType.PARAMETER

     can be applied to the parameters of a method.
  • ElementType.TYPE

     can be applied to any element of a class.
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}
           

@Inherited

訓示注解可以被繼承。假設被@Inherited注釋的注解為@A,如果父類被@A注釋,子類便可以繼承這個注解。但是并不完全對,因為通過反射,子類不能找到@A。

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

@Repeatable

被@Repeatable注解的注解可以在一個地方使用多次,比如下面的@Schedule可以使用多次:

@Schedule(dayOfMonth="last")
@Schedule(dayOfWeek="Fri", hour="23")
public void doPeriodicCleanup() { ... }
           

但是由于相容原因,repeatable注解(就是被@Repeatable注釋過的注解)需要被存入容器注解(container annotation)。也就是說定義repeatable注解時還需要定義容器注解。下面聲明repeatable注解:

@Repeatable(Schedules.class)
public @interface Schedule {
  String dayOfMonth() default "first";
  String dayOfWeek() default "Mon";
  int hour() default 12;
}
           

@Repeatable中需要指定容器注解,容器注解的定義為:

public @interface Schedules {
    Schedule[] value();
}
           

注意,容器注解的元素value數組中的類型一定要為repeatable注解類型。很拗口吧,但是既然要存入repeatable注解(也就是Schedule),當然要定義它的數組(Schedule[])。

五、其他

一些注解可以用于類型的使用上,被稱為類型注解(type annotation),通常被用于類型檢測。

參考:

https://docs.oracle.com/javase/tutorial/java/annotations/index.html

http://tutorials.jenkov.com/java/annotations.html

https://www.developer.com/java/other/article.php/10936_3556176_3/An-Introduction-to-Java-Annotations.htm

https://blog.usejournal.com/how-much-do-you-actually-know-about-annotations-in-java-b999e100b929