1. 程式人生 > 實用技巧 >題解 CF1136E 【Nastya Hasn't Written a Legend】

題解 CF1136E 【Nastya Hasn't Written a Legend】

一、什麼是註解?

Annotaion

  • 註解(Annotaion)是從JDK5.0開始引入的一種新技術稱之為註解機制。

  • 註解(Annotaion)的格式:

    • 註解是以"@註釋名"在程式碼中使用的,可以新增一些引數值,例如:@GetMapping("/get")
  • 註解(Annotaion)可以使用的範圍:

    • 可以在package、class、method、field等上面使用。例如

    • @Controller
      public class RequestController {
          
          @DeleteMapping("/delete")
          @ResponseBody
          
      public String delete(String name,Integer id){ JSONObject json = new JSONObject(); json.put("requestType","deleteType"); json.put("name",name); json.put("id",id); return json.toString(); } }
      • 我們可以通過反射機制程式設計對這些元資料的訪問。

      • 註解有一些特定的功能,例如:

        • 當你如果要重寫toString()方法的時候,不是按照規定的名字來寫的話,就會報錯:

        • 正常的話,是不會報錯的:

        • 說明@Override註解帶有檢查的作用。

二、內建註解

Java內部定義了一套註解,共有7個:

註解名稱作用
@Override 檢查該方法是否是重寫方法。如果發現其父類,或者是引用的介面中並沒有該方法時,會報編譯錯誤。
@Deprecated 標記過時方法。如果使用該方法,會報編譯警告。
@SuppressWarnings 指示編譯器去忽略註解中宣告的警告。

作用在其他註解的註解(元註解):在java.lang.annotaion包中

註解名稱作用
@Retention 標識這個註解怎麼儲存,是隻在程式碼中,還是編入class檔案中,或者是在執行時可以通過反射訪問。
@Documented 標記這些註解是否包含在使用者文件中。
@Target 標記這個註解應該是哪種 Java 成員。
@Inherited 標記這個註解是繼承於哪個註解類(預設 註解並沒有繼承於任何子類)

從 Java 7 開始,額外添加了 3 個註解:

註解名稱作用
@SafeVarargs Java 7 開始支援,忽略任何使用引數為泛型變數的方法或建構函式呼叫產生的警告。
@FunctionalInterface Java 8 開始支援,標識一個匿名函式或函式式介面。
@Repeatable Java 8 開始支援,標識某註解可以在同一個宣告上使用多次。

三、元註解的使用

(一)前期準備

如果你想自定義註解,那麼元註解是必知必會必懂的。

元註解就是註解自定義註解的註解。可能有點饒,一會看例子就明白了,直白點就是給你自定義的註解上一定要加的註解

作用在其他註解的註解(元註解):在java.lang.annotaion包中

註解名稱作用
@Retention 標識這個註解怎麼儲存,是隻在程式碼中,還是編入class檔案中,或者是在執行時可以通過反射訪問。
@Documented 標記這些註解是否包含在使用者文件中。
@Target 標記這個註解應該是哪種 Java 成員。
@Inherited 標記這個註解是繼承於哪個註解類(預設 註解並沒有繼承於任何子類)

我們定義一個類,類的作用就是用來測試我們定義的註解:

/**
 * @Auther: truedei
 * @Date: 2020 /2020/9/6 18:11
 * @Description: 自定義註解測試
 */
public class Test {

}

然後建立一個類,把class識別符號改成@interface:這就是自定義好的註解了。

/**
 * @Auther: truedei
 * @Date: 2020 /2020/9/6 19:00
 * @Description: 自定義註解
 */
public @interface MyAnnotaion {

}

現在可以看到就可以使用了,只不過沒有任何的功能:

(二)@Target的用法詳解

我們來賦予一定的功能,來標識這個註解的作用:

加上元註解:@Target,就是用來指出對什麼生效,作用的目標是什麼,可以在什麼地方使用。

可以看到傳遞的是一個E

可以點看@Target的原始碼看一下:

可以看到下面這種情況。

需要提前知道的是,value()是接收的引數,並不是一個方法。

那麼Target就需要接收一個ElementType[]的陣列。

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

    ElementType[] value();
}

沒加之前,先改造一下:

可以看到這個註解什麼都沒加,既可以加在類上,也可以加在方法上,也可以加在變數上。

如果我們想做限制呢?只允許我們的這個註解對類生效

我們先來看一下Controller註解這個應該不陌生,就不解釋了。

那麼我們也可以加上這個:

可以看到效果了,只要類上的生效了,其餘的都報錯了。

那麼這就是元註解Target的作用。

看一下ElementType.java中列舉的引數,這些都可以使用,瞭解下就好。

package java.lang.annotation;

public enum ElementType {
    TYPE,               /* 類、介面(包括註釋型別)或列舉宣告  */

    FIELD,              /* 欄位宣告(包括列舉常量)  */

    METHOD,             /* 方法宣告  */

    PARAMETER,          /* 引數宣告  */

    CONSTRUCTOR,        /* 構造方法宣告  */

    LOCAL_VARIABLE,     /* 區域性變數宣告  */

    ANNOTATION_TYPE,    /* 註釋型別宣告  */

    PACKAGE             /* 包宣告  */

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}

如果你想讓你的註解對什麼生效,就指定好就OK:

(三)@Retention的用法詳解

Retention中需要傳遞RetentionPolicy。

RetentionPolicy.java有三個列舉引數,如下:

package java.lang.annotation;
public enum RetentionPolicy {
    SOURCE,            /* Annotation資訊僅存在於編譯器處理期間,編譯器處理完之後就沒有該Annotation資訊了  */

    CLASS,             /* 編譯器將Annotation儲存於類對應的.class檔案中。預設行為  */

    RUNTIME            /* 編譯器將Annotation儲存於class檔案中,並且可由JVM讀入 */
}

一般都是呼叫**RUNTIME**,呼叫RUNTIME我們可以通過反射拿到相關的資料,來進行處理等。

由於這個不太好驗證,就不一一驗證了,瞭解就好