Android Annotation ——XArch

  註解並不是第一次看到,類似於見過最多的 @Override 

【遇】

  BaseActivity中實現了 IGetPageName 接口,接口中 定義了 getPageName方法,添加 @PageName 註解,MainActivity中重寫BaseActivity中的 getPageName 方法並設置返回值,這裏達到了返回值只能設置爲 PageName枚舉中值的效果,而枚舉使用靜態常量+@StringDef 的方法定義。

@PageName 自定義註解,@StringDef (androidx.annotation包內)

BaseActivity.java

IGetPageName.java

PageName.java

 

 MainActivity.java

 

【問】

註解是什麼,註解有什麼作用?

在什麼情況下會想到要使用註解?

 

【知】

參考博文:Java Annotation認知(包括框架圖、詳細介紹、示例說明) - 如果天空不死 - 博客園 (cnblogs.com)

1、 Java Annotation是JDK5.0引入的一種註釋機制

2、我對於Annotation的理解

  

  ElementType、RetentionPolicy是枚舉,Annotation是一個接口。然後我們由他們創建新的Annotation註解。新的註解,就是通過實現 Annotation的接口,然後再通過@Target、@Retention註解分別來指定ElementType、RetentionPolicy的值,結構圖中1..n表示@Target可以指定多個枚舉值(用來只能註解可以修飾的位置),而@Retention註解就只能指定一個枚舉值(表示註解作用域,保留到的位置)。

  ①@Target本身也是註解,那麼上面說註解創建時就要通過@Target來修飾Target的註解。所以存在以下代碼

  

 ⭐爲什麼@Target能夠修飾 Target Annotation?不是還在創建階段嗎

  有關於這個問題,我還沒有答案。有人回答我說,就像遞歸,自己調用自己。對哇,遞歸,我以前爲什麼沒有問,函數爲什麼能夠自己調用自己?(從網上我得出的理解時,方法定義並不分配內存,而是相當於存儲一個方法的指針,調用的時候再去執行具體的方法,所以當它調用自己的時候,它早就已經告訴編譯器,它存在了。爲什麼函數能遞歸調用自己? - 知乎 (zhihu.com)

  除了@Target修飾Target,還存在@Target修飾 Retention 創建,@Retention修飾Target創建,這或許有點像在A函數裏面調用B函數,B函數裏面調用A函數。

  很難解釋,那麼是否可以跳過Target 創建,把@Target單純看做成對該註解的註解。即我們只需要知道 @Target 只能修飾 ANNOTATION_TYPE(像這種只能修飾註解的註解稱爲元註解),JDK提供了一系列其他的註解,我們可通過註解上方的註解,瞭解這個註解的作用域和作用。

 

  ②ElementType枚舉值以及說明

 

 

   ③RetentionPolicy的枚舉值及說明

 

  ④元註解:修飾註解的註解,以下四個

@Documented  -- @Documented 所標註內容,可以出現在javadoc中。若不設置默認爲否
@Inherited   -- @Inherited只能被用來標註“Annotation類型”,它所標註的Annotation具有繼承性。就是使用該Annotation的類的子類也自動繼承該父類的註解。若不設置默認爲否
@Retention   -- @Retention只能被用來標註“Annotation類型”,而且它被用來指定Annotation的RetentionPolicy屬性。若不設置默認爲RetentionPolicy.CLASS
@Target      -- @Target只能被用來標註“Annotation類型”,而且它被用來指定Annotation的ElementType屬性。若不設置默認爲可作用域任何地方
@Repeatable  -- @Repeatable(重複) 用於聲明標記的註解爲可重複類型註解,可以在同一個地方多次使用

 

  ⑤其他註解

@SuppressWarnings -- @SuppressWarnings 所標註內容產生的警告,編譯器會對這些警告保持靜默。
@Deprecated  -- @Deprecated 所標註內容,不再被建議使用。

 

3、kotlin中的Annotation 有什麼不同

  ①元註解不同 @Documented改成 @MustBeDocumented

去掉了@Inherited(查看:Inherited annotations and other reflections enchancements - Support - Kotlin Discussions (kotlinlang.org)

  ②ElementType名對應AnnotationTarget,RetentionPolicy名對應AnnotationRetention

  ③@Retention的默認值不同,Java中默認值爲 RetentionPolicy.CLASS,Kotlin中是AnnotationRetention.RUNTIME

package kotlin.annotation

import kotlin.annotation.AnnotationTarget.*

/**
 * Contains the list of code elements which are the possible annotation targets
 */
public enum class AnnotationTarget {
    /** Class, interface or object, annotation class is also included */
    CLASS,
    /** Annotation class only */
    ANNOTATION_CLASS,
    /** Generic type parameter */
    TYPE_PARAMETER,
    /** Property */
    PROPERTY,
    /** Field, including property's backing field */
    FIELD,
    /** Local variable */
    LOCAL_VARIABLE,
    /** Value parameter of a function or a constructor */
    VALUE_PARAMETER,
    /** Constructor only (primary or secondary) */
    CONSTRUCTOR,
    /** Function (constructors are not included) */
    FUNCTION,
    /** Property getter only */
    PROPERTY_GETTER,
    /** Property setter only */
    PROPERTY_SETTER,
    /** Type usage */
    TYPE,
    /** Any expression */
    EXPRESSION,
    /** File */
    FILE,
    /** Type alias */
    @SinceKotlin("1.1")
    TYPEALIAS
}

/**
 * Contains the list of possible annotation's retentions.
 *
 * Determines how an annotation is stored in binary output.
 */
public enum class AnnotationRetention {
    /** Annotation isn't stored in binary output */
    SOURCE,
    /** Annotation is stored in binary output, but invisible for reflection */
    BINARY,
    /** Annotation is stored in binary output and visible for reflection (default retention) */
    RUNTIME
}

/**
 * This meta-annotation indicates the kinds of code elements which are possible targets of an annotation.
 *
 * If the target meta-annotation is not present on an annotation declaration, the annotation is applicable to the following elements:
 * [CLASS], [PROPERTY], [FIELD], [LOCAL_VARIABLE], [VALUE_PARAMETER], [CONSTRUCTOR], [FUNCTION], [PROPERTY_GETTER], [PROPERTY_SETTER].
 *
 * @property allowedTargets list of allowed annotation targets
 */
@Target(AnnotationTarget.ANNOTATION_CLASS)
@MustBeDocumented
public annotation class Target(vararg val allowedTargets: AnnotationTarget)

/**
 * This meta-annotation determines whether an annotation is stored in binary output and visible for reflection. By default, both are true.
 *
 * @property value necessary annotation retention (RUNTIME, BINARY or SOURCE)
 */
@Target(AnnotationTarget.ANNOTATION_CLASS)
public annotation class Retention(val value: AnnotationRetention = AnnotationRetention.RUNTIME)

/**
 * This meta-annotation determines that an annotation is applicable twice or more on a single code element
 */
@Target(AnnotationTarget.ANNOTATION_CLASS)
public annotation class Repeatable

/**
 * This meta-annotation determines that an annotation is a part of public API and therefore should be included in the generated
 * documentation for the element to which the annotation is applied.
 */
@Target(AnnotationTarget.ANNOTATION_CLASS)
public annotation class MustBeDocumented

   ④定義Annotation的方法不同

     java中使用 @interface ,kotlin 中使用 annotation class。

  ⑤枚舉中的部分字段就不同。比如Java中RetentionPolity.CLASS對應 Kotlin中AnnotationRetention.BINARY,ElementType.ANNOTATION_TYPE 對應 AnnotationTarget.ANNOTATION_CLASS 但功能類似,改成了更爲可讀名稱

@Retention(AnnotationRetention.SOURCE)
annotation class PageName{
    //語法形式上模擬了靜態類的調用方法
    companion object{
        const val MAIN = "main"
        const val HOME = "home"
        const val ACGN = "acgn"
        const val SMALL_VIDEO = "small_video"
        const val GOLD = "gold"
        const val MINE = "mine"
        const val ABOUT = "about"
        const val DISCOVERY = "discovery"
    }
}

 

4、Androidx中的一些註解(androidx.annotation  |  Android Developers (google.cn)

  • 爲什麼enum影響性能?

        因爲沒有enum的值都會創建了一個Object對象,佔用內存。

 

5、爲什麼@PageName能夠限定方法的返回值是PageName內枚舉值

      這裏@PageName和@StringDef結合,實際上達到的是枚舉的作用效果,可以方法參數前面,或者方法上方,指定參數的傳值區間和返回值區間。這裏是用作枚舉。

 

6、有關PermissionX使用註解對是否請求權限的檢查

 

【註解的作用】

1、編譯檢查

@PageName實際上也是起到這樣的效果、@Override

2、生成對應的幫助文檔

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章