您好,登錄后才能下訂單哦!
這篇文章主要講解了“Java里的注解是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Java里的注解是什么”吧!
java注解是jdk1.5以后新出的特性,對于它的應用非常廣泛,我們首先來看一下注解的應用,百度百科上這樣說:
我們可以看到,注解的作用有三方面:
編寫doc文檔:這個就我們很常用的 @return 以及 @author,加了這些注解以后,就可以用jdk幫我們自動生成對應的API文檔了
編譯檢查:這個也很常見 @Override,而且功能很強大,我將會在以后的文章中介紹
進行代碼分析:這是本篇文章的重點。這個和編譯檢查一樣也是一個強大的功能,但相比與編譯檢查由于其用到了反射,在性能上存在一些問題
后臺開發中的SSH三大框架,以及咱們安卓端的retrofit,ButterKnife,Lombok等框架和插件也是大量的用到了注解。這里我將通過手擼一個假的ButterKnife來具體演示注解有什么用,怎么用。
我們首先來看段代碼
public class MainActivity extends AppCompatActivity { @OnClick(R.id.test_btn) void test(){ test_tv.setText("恭喜您,綁定成功了!"); } @FindViewByID(R.id.test_tv) TextView test_tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bindView(this); } }
這是一個最基本的activity,里面有2個控件,Button和TextView
在我點擊Button后TextView的文字被改變。而我所做的僅僅是ButterKnife.bindView(this)并添加2個注解而已,這樣就實現了控件的綁定,省去了很多與業務無關的代碼,是不是簡潔了很多。
看了注解的功能是不是很想了解它是怎么做到的,接下來我就來看看它是什么,怎么用,怎么利用
什么是注解
官方把它叫做元數據,即一種描述數據的數據。所以,可以說注解就是源代碼的元數據。用它來可以來描述、標記我們的源代碼。
怎樣定義一個注解
以下是我上文中定義的一個 @OnClick注解
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface OnClick { int value() default 0; }
可見和定義一個類一樣,只是將class改為 @interface,并且頂部通過幾個原注解來說明這個注解的一些重要信息,具體如下:
J2SE5.0版本在 java.lang.annotation提供了四種元注解,專門注解其他的注解:
@Documented –注解是否將包含在JavaDoc中
@Retention –什么時候使用該注解
@Target? –注解用于什么地方
@Inherited – 是否允許子類繼承該注解
@Documented–一個簡單的Annotations標記注解,表示是否將注解信息添加在java文檔中,一般不用管。
@Retention– 定義該注解的生命周期,很重要,必須指定,以下是3種生命周期的介紹
RetentionPolicy.SOURCE – 在編譯階段丟棄。這些注解在編譯結束之后就不再有任何意義,所以它們不會寫入字節碼。@Override, @SuppressWarnings都屬于這類注解。
RetentionPolicy.CLASS – 在類加載的時候丟棄。在字節碼文件的處理中有用。注解默認使用這種方式。
RetentionPolicy.RUNTIME– 始終不會丟棄,運行期也保留該注解,因此可以使用反射機制讀取該注解的信息。我們自定義的注解通常使用這種方式。
@Target – 表示該注解用于什么地方。如果不明確指出,該注解可以放在任何地方。以下是一些可用的參數。需要說明的是:屬性的注解是兼容的,如果你想給7個屬性都添加注解,僅僅排除一個屬性,那么你需要在定義target包含所有的屬性。
ElementType.TYPE:用于描述類、接口或enum聲明
ElementType.FIELD:用于描述實例變量
ElementType.METHOD
ElementType.PARAMETER
ElementType.CONSTRUCTOR
ElementType.LOCAL_VARIABLE
ElementType.ANNOTATION_TYPE 另一個注釋
ElementType.PACKAGE 用于記錄java文件的package信息
@Inherited – 定義該注釋和子類的關系
那么注解體里的內容有該怎樣定義
Annotations只支持基本類型、String及枚舉類型。注釋中所有的屬性被定義成方法,并允許提供默認值。
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface Book{ public enum Priority {LOW, MEDIUM, HIGH} String author() default "Yash"; int price() default 20; Status status() default Status.NOT_STARTED; }
看看怎么用它
@Todo(priority = Todo.Priority.MEDIUM, author = "zsq", status = Todo.Status.STARTED) public void incompleteMethod1() { }
通過字段名 = 的形式給字段賦值,如果沒賦值,則使用缺省值。如果注解中只有一個屬性,可以直接命名為“value”,使用時無需再標明屬性名,例如我定義的 @OnClick注解。
好了,花了那么多精力來認識他,該看看該怎么來利用它了
我們定義了自己的注解并將其應用在業務邏輯的方法上。現在我們需要寫一個用戶程序調用我們的注解。這里我們需要使用反射機制。如果你熟悉反射代碼,就會知道反射可以提供類名、方法和實例變量對象。所有這些對象都有getAnnotation()這個方法用來返回注解信息。我們需要把這個對象轉換為我們自定義的注釋(使用 instanceOf()檢查之后),同時也可以調用自定義注釋里面的方法。
所有這些對象都有getAnnotation()!
所有這些對象都有getAnnotation()!
所有這些對象都有getAnnotation()!
重要的API說3遍,另外用到的幾個方法也很重要,下面的代碼會演示,更多的API使用參考可以去查閱JDK文檔。
具體到我們本編文章的實例,調用注解的家伙就是我們剛剛在MainActivity里用到的 ButterKnife,我們通過設置監聽的注解來看看它到底做了什么
public static final void bindView(final Activity activity){ traversalMethod(activity); traversalField(activity); }
在我們調用的ButterKnife.bindView(this)中我們拿到了MainActivity的實例,并且通過反射遍歷里面所有的方法:
private static void traversalMethod(final Activity activity) { Method[] methodArray = getObjectMethodArray(activity); for (final Method method:methodArray){ if(isAnnotationPresent(method)){ int viewID = getViewID(method); setOnClickListenerForControl(activity, method, viewID); } } } private static Method[] getObjectMethodArray(Activity activity) { return activity.getClass().getMethods(); }
接著判斷方法是否被我們注解:
private static boolean isAnnotationPresent(Method method) { return method.isAnnotationPresent(OnClick.class); }
如果是我們用注解標注的方法則通過注解獲取注解里保存的空間ID,并且通過MainActivity的實例為其設置點擊監聽,在監聽內調用被注解標注的方法。
private static int getViewID(Method method) { return method.getAnnotation(OnClick.class).value(); } private static void setOnClickListenerForControl(final Activity activity, final Method method, int viewID) { activity.findViewById(viewID).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try { method.invoke(activity); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }); }
大功告成!是不是很簡單
感謝各位的閱讀,以上就是“Java里的注解是什么”的內容了,經過本文的學習后,相信大家對Java里的注解是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。