日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Java和Android中的注解

發布時間:2023/12/3 Android 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java和Android中的注解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自??Java和Android中的注解

1.引言

從JDK1.5開始,引入了注解類Annotation,Annotation其實是一種接口,可以作用于類、方法、屬性等等 ,它可以通過反射機制來訪問annotation信息,獲取所加上注解信息,做相應的操作。相當于給相關的作用對象打上“tag”,使用方便,作用廣泛。

2.java.lang中的注解

? ? ?在java.lang中,用到三種注解類,即常用到的Deprecated,Override和SuppressWarnings.

? ? ?2.1 @Deprecated 過時

? ? ?在使用Eclipse或AS編寫程序過程中,有一些方法編寫出來之后被畫上了中劃線,表示該方法已過時,建議使用新的一些方法代替。
?????如:viewPager.setOnPageChangeListener()方法在安卓API23中已過時,在源代碼中的該方法上赫然多了一個注解@Deprecated,可使用addOnPageChangeListener()方法代替。
? ? ?如果使用javac命令編譯,會彈出:”注意:使用或覆蓋了已過時的API“

? ? ?2.2 @Override 復寫

? ? ?這是開發過程中最常遇到的注解了,表示復寫父類中的方法。如果方法上有這條注解但沒有重寫父類方法,則會生成一條錯誤消息。這個注解有效地保證了方法一定會被復寫。比如開發過程中,手動在子類中復寫父類方法,只正確寫出了方法名稱,未寫正確方法的參數,則相當于方法的重載,并不是復寫。這種問題如果在功能上有錯誤產生,在檢查過程中是很難找到的。使用@Override注解,有效地表明,此方法是復寫父類的方法,不會產生手動的錯誤問題。

? ? ?2.3 @SuppressWarnings 阻止警告

? ? ?阻止了彈出的警告,比如屏蔽對上述過時的提示,可在調用setOnPageChangeListener()方法之上加上@SuppressWarnings("deprecation"),這樣雖然在IDE中仍以中劃線的形式表示,但如果使用javac命令就不再提示警告。

3.元注解

? ? ?那么以上的注解類的源碼又是什么樣的呢,打開Override發現其代碼如下

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

這里可以發現注解類的定義方法以及注解類上所加的注解——元注解。元注解有四個,位于java.lang.annotation包中:Documented,Inherited,Retention,Target

? ? ?3.1@Target

? ? ?表示注解作用的目標。

@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Target { ElementType[] value(); }

注解可以作用的目標由枚舉類ElementType決定,可作用于類、方法、屬性等,數組表示注解可以有多個作用域。

public enum ElementType { TYPE,// 類、接口、注解類型或枚舉 FIELD, //屬性 METHOD, //方法 PARAMETER,// 用于描述參數 CONSTRUCTOR,//構造方法 LOCAL_VARIABLE,//局部變量 ANNOTATION_TYPE,//注解類 PACKAGE //包 }

注解作用于類時,定義@Target(ElementType.TYPE),ElementType .TYPE表示類型,Class,Interface等都實現了java中的Type接口,因此ElementType.TYPE?表示注解作用于這些"類"(并不是單純的Class類)

? ? ?3.2@Retention

? ? ?表示注解的作用時段

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

由此可見,Retention定義的是RetentionPolicy類型的數據,RetentionPolicy是一個枚舉類型,包括SOURCE,CLASS,RUNTIME三個類型。表示注解保留的階段。
SOURCE:表示注解只在源文件中保留
CLASS:表示注解保留到.class文件中
RUNTIME:表示注解一直保留到內存中,類加載器把.class文件加載到內存中產生的字節碼中要保留注解信息。
可想而知,@Override僅在寫代碼時用到,其Retention中的值為RetentionPolicy.SOURCE,@SuppressWarnings也只是編譯器使用的,保留到SOURCE階段。而@Deprecated在內存中也需要保留,編譯器需要得知方法是否過時,從加載到內存中的二進制文件中獲取,因而要保留到RUNTIME階段


? ? ?3.3@Documented?

注解只是一個標記的話,那么使用javadoc生成文檔時,這些注解都不會存在于文檔中,要使注解在文檔中也存在,就可以在使用了注解的作用對象上加上@Documented這個注解。javadoc所生成的文檔就會帶上注解信息。

? ? ?3.4@Inherited

該注解表示子類可以集成加載父類上的注解。但要注意: 1.注解定義在類上面,子類是可以繼承該注解 2.注解定義在方法上面,子類也可以繼承該注解,但是如果子類復寫了父類中定義了注解的方法,那么子類將無法繼承該方法的注解,也就是說,子類在復寫父類中被@Inherited標注的方法時,會將該方法上面的注解覆蓋掉 3.Interface的實現類(implements實現)無法繼承接口中所定義的被@Inherited標注的注解

4.注解的參數

在注解后為注解增加參數,如上述的@Retention、@Target后的括號中就是注解的參數。 參數的類型,支持基本數據類型、String類型、Class類型、enum類型、Annotation類型以及上述所有類型的數組。 當注解只有一個參數時,可以用value作為參數名稱,在使用參數時,只用在括號中寫參數的值而不用寫參數名稱。若存在多個參數時,需寫上對應的參數名,并賦值,如@Subscribe(tag="xx"),若參數為數組類型,則需賦值形如:@Target({ElementType.TYPE,ElementType.METHOD})

5.自定義注解

從上面的注解中,也大致看到了注解的定義方式。 1.使用@interface定義一個注解類,其內部自行繼承了Annotation類。 2.在該類中定義注解的參數,定義方式很像方法。 3.注解元素必須有確定的值,要么在定義注解的默認值中指定,要么在使用注解時指定,非基本類型的注解元素的值不可為null。因此, 使用空字符串或0作為默認值是一種常用的做法。定義一些特殊的值,例如空字符串或者負數,表示某個元素不存在參數設置默認值時,后面跟上default即可設置默認值。 4.當注解的參數只有一個時,建議用value作為參數名,這樣在使用注解時,可以直接寫參數的值 接下來自定義一個注解類: @Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Car{ String name() default ""; int number() default -1; } 再定義一個類去使用這個注解: @Car(name="好車",number=666) public class CarBMW(){ } 那么如何獲取這些注解值呢?有如下的方法: if(CarBMW.class.isAnnotationPresent(Car.class)){//判斷CarBMW類是否有注解類Car Car carAnnotation=(Car)CarBMW.class.getAnnotation(Car.class);//獲取注解實例對象 Log.v("Shawn",carAnnotation.name());//獲取name參數的值 Log.v("Shawn",carAnnotation.number());//獲取number參數的值 }

5.1 JAVA8中注解的補充

在JAVA8中,增加了TypeAnnotation,在 Java 8 之前的版本中,只能允許在聲明式前使用 Annotation。而在 Java 8 版本中,Annotation 可以被用在任何使用 Type 的地方,例如:初始化對象時 (new),對象類型轉化時。

//初始化對象時 String myString = new @NotNull String(); //對象類型轉化時 myString = (@NonNull String) str; 這點上有點類似Android中的注解使用。
而ElementType中增加了倆個值ElementType. T YPE_PARAMETER 和ElementType. TYPE_USE ?正是為此功能實現而產生的。
ElementType. TYPE_PARAMETER ?表示這個 Annotation 可以用在 Type 的聲明式前,而 ElementType .TYPE_USE? 表示這個 Annotation 可以用在所有使用 Type 的地方(如:泛型,類型轉換等)。
Type Annotation 也可以通過設置 Retention 在編譯后保留在 class 文件中(RetentionPolicy.CLASS)或者運行時可訪問(RetentionPolicy.RUNTIME)。但是與之前不同的是,Type Annotation 有兩個新的特性:在本地變量上的 Annotation 可以保留在 class 文件中,以及泛型類型可以被保留甚至在運行時被訪問。
此外,JAVA8中還增加了一個特性RepeatingAnnotation,允許為同一個聲明式或者類型加上相同的 Annotation。

例如:一個類可以被兩個人使用:

@Worker(role="XiaoMing") @Worker(role="XiaoHong") public class Person { ... }

需要需要重復標注特性的 Annotation 前加上 @Repeatable 標簽

@Repeatable(Workers.class) public @interface Worker{ String role(); } @Repeatable 標簽后括號中的值即為指定的 Container Annotation 的類型。在這個例子中,Container Annotation 的類型是 Workers,Java 編譯器會把重復的 Worker 對象保存在 Workers中。

Workers中必須定義返回數組類型的value()方法。數組中元素的類型必須為對應的 Repeating Annotation 類型。具體示例如下:

public @interface Workers{ Worker[] value(); } 獲取注解的方法有兩種:

一種方式是用過 上述的的 getAnnotations(Class<T>) 方法一次性返回 Repeating Annotation。

另一種方式是通過 AnnotatedElement 接口的 getAnnotationByType(Class<T>) 首先獲得 Container Annotation,然后再通過 Container Annotation 的 value 方法獲得 Repeating Annotation。

Workers workers= Person.class.getAnnotation(Workers.class); Worker[] workers2= Person.class.getAnnotationsByType(Worker.class); 以上關于JAVA8中的注解參考 http://www.ibm.com/developerworks/cn/java/j-lo-java8annotation/index.html

6.Android中的注解

6.1兩個常見的注解

Android從API16引入了annotation包,包括兩個注解@TargetApi和@SuppressLint @TargetApi (Build.VERSION_CODES.XX)用于屏蔽某一新api中才能使用的方法報的lint檢查出現的錯誤。 @SuppressLint("NewApi") 屏蔽一切新api中才能使用的方法報的android lint錯誤
當然,這兩個注解的作用僅僅是屏蔽lint錯誤,在方法中還要判斷版本做不同的操作,比如: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.XX) { //高于XX版本進行的操作 } else { //低于XX版本進行的操作 }

6.2Android中用到的注解

API19引入了很多注解,起初是以jar包形式引入的,放在SDK目錄下sdk\extras\android\m2repository\com\android\support\support-annotations\ 在API21之后,直接放入了annotation包中 Android中的注解分為八類,在API23中有42個注解類

6.2.1 @CallSuper

要求方法必須調用父類方法,可想而知,Activity的onCreate()方法有此注解標識。

6.2.2 @NonNull和@Nullable ? ??

定義一個變量或對象可以為空或不可為空,用在方法上表示方法可否返回空。

6.2.3 資源類注解

@AnimatorRes,@AnimRes,@AnyRes,@ArrayRes,@AttrRes,@ BoolRes,@ ColorRes,@ DimensRes,@ DrawableRes,@ FractionRes,@ IdRes,@ IntegerRes,@ InterpolatorRes,@ LayoutRes,@ MenuRes,@ PluralsRes,@ RawRes,@ StringRes,@ StyleableRes,@StyleRes,@ TransitionRes,@ XmlRes 這部分注解是非常有實用性的,有22個,用法如: getDrawable(@DrawableRes int id) //getDrawable方法限定了傳入的參數必須是Drawable資源文件 另外還有個@ColorInt,限制傳入Hex顏色值。 在開發過程中需要傳入某種資源文件時,用此類注解,是很有限制作用的做法。

6.2.4@IdDef和@StringDef

提到最常用的Toast,在API21之前,一般可以這么寫 Toast.makeText(context, "msg",?0).show(); 但是21之后,0突然被劃紅線了,查看源碼發現,之前是這么寫的: public static final int LENGTH_SHORT = 0; public static final int LENGTH_LONG = 1; makeText方法中單純地寫著int duration參數,而21之后,成了這樣: @IntDef({LENGTH_SHORT, LENGTH_LONG}) @Retention(RetentionPolicy.SOURCE) public @interface Duration {} 在makeText的duration參數之前加上了注解@Duration,這就要求傳入Duration中的值才不會報警告。 可以想象,@IntDef和@String Def中放入了一個value數組。 在開發中,這兩個注解就可以用來限制枚舉值了。

6.2.5 范圍約束@FloatRange、@IntRange和@Size

前兩個限制了數字的范圍,比如可以用來限制傳入參數值的范圍, @Size可以用來限定集合的大小或者限定字符串的長度,還可以做其他限制: 1.限制最小最大數量:@Size(min=1,max=10 ) 2.數量必須是2的倍數(偶數): @Size(multiple=2)

6.2.6 進程類注解

@UiThread,@BinderThread,@MainThread,@WorkerThread 用來限定方法或類在指定的線程類型中被調用,比如 AsyncTask中的方法就有如下的限定: @WorkerThread protected abstract Result doInBackground(Params... params){ //doInBackground } @MainThread protected void onProgressUpdate(Progress... values) { //onProgressUpdate }

6.2.7@CheckResult

該注解意味著需要對方法的返回值進行處理,例如:有個方法為 @CheckResult public boolean checkValid(String value){ return TextUtils.isEmpty(value); } 當調用者直接調用checkValid("abc");時會報錯,這意味著,需要對方法的返回值進行處理,無論返回true或false,需要進行后續操作,不能單單調用一句checkValid("abc");

6.2.8 權限注解@RequiresPermission

如果方法的調用需要權限,可以加這個注解,當需要幾個權限中的一個時,使用anyOf,如 @RequiresPermission(anyOf?=?{?Manifest.permission.ACCESS_COARSE_LOCATION,?Manifest.permission.ACCESS_FINE_LOCATION}) 若需要多個權限,使用allOf,如 @RequiresPermission(allOf?=?{?Manifest.permission.READ_EXTERNAL_STORAGE,?Manifest.permission.WRITE_EXTERNAL_STORAGE})
若需要單獨的標注讀和寫的權限訪問,所以可以用@Read或者@Write標注每一個權限需求

6.2.9 @SdkConstant

表示一個常量字段應該被輸出在SDK工具中使用,例如: 添加一個自定義的Action: @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_MY_TEST = "android.intent.action.MY_TEST"; 則可以這樣使用: Intent myTest = new Intent(Intent.ACTION_MY_TEST); mContext.sendBroadcast(myTest);


6.2.10@Widget

用于類的注解,表示該類是自定義的Widget類
此外還有兩個注解即上述的@TargetApi和@SuppressLint不再贅述。

7.總結

綜上,注解部分就介紹完了。注解在開發過程中有很強的實用性,使用注解可以明確開發過程中的一些數據類型,還可以對一些數據進行限制,從而提高開發效率。

總結

以上是生活随笔為你收集整理的Java和Android中的注解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。