摘要:從開(kāi)始,增加了對(duì)元數(shù)據(jù)的支持,也就是注釋。該注解只能夠修飾接口,不能夠修飾其他程序元素。程序處代碼使用類來(lái)處理本程序中的注解,該處理器分析目標(biāo)對(duì)象中的所有成員變量,如果該成員變量簽使用了修飾,則取出
從JDK 5開(kāi)始,Java增加了對(duì)元數(shù)據(jù)(MetaData)的支持,也就是Annotation(注釋)。Annotation提供了一種為程序元素設(shè)置元數(shù)據(jù)的方法,從某些方面來(lái)看,Annotation就想修飾符一樣,可用于修飾包、類、構(gòu)造器、方法、成員變量、參數(shù)、局部變量的聲明,這些信息被存儲(chǔ)在Annotation的”name = value”對(duì)中
Annotation是一個(gè)接口,程序可以通過(guò)反射來(lái)獲取指定程序元素的Annotation對(duì)象,然后通過(guò)Annotation對(duì)象來(lái)取得注釋里的元數(shù)據(jù)
Annotation能被用來(lái)為程序元素(類、方法、成員變量等)設(shè)置元數(shù)據(jù),且不會(huì)影響程序代碼的執(zhí)行,無(wú)論增加、刪除Annotation,代碼都始終如一地執(zhí)行。如果希望讓程序中的Annotation在運(yùn)行時(shí)起一定的作用,只有通過(guò)某種配套的工具對(duì)Annotation中的信息進(jìn)行訪問(wèn)和處理,訪問(wèn)和處理Annotation的工具統(tǒng)稱為APT(Annotation Processing Tool)
基本Annotation使用Annotation時(shí)要在其前面增加@符號(hào),并把該Annotation當(dāng)成一個(gè)修飾符使用,用于修飾它支持的程序元素
5個(gè)基本的Annotation
@Override
@Deprecated
@SuppressWarnings
@SafeVarargs
@FunctionalInterface
限定重寫父類方法:@Override@Override 就是用來(lái)指定方法覆載,它可以強(qiáng)制一個(gè)子類必須覆蓋父類的方法。@Override的作用是告訴編譯器檢查這個(gè)方法,保證父類要包含一個(gè)被該方法重寫的方法,否則就會(huì)編譯出錯(cuò)。@Override主要是幫助程序員避免一些低級(jí)錯(cuò)誤,如重寫info()方法,卻手誤寫成了inf(),編譯器不會(huì)報(bào)錯(cuò),你可能找半天才能找到錯(cuò)誤
@Override 只能修飾方法,不能修飾其他程序元素
標(biāo)示已過(guò)時(shí):@Deprecated@Deprecated 用于表示某個(gè)程序元素(類,方法等)已過(guò)時(shí),當(dāng)其他程序使用已過(guò)時(shí)的類,方法時(shí),編譯器將會(huì)給出警告
抑制編譯器警告:@SuppressWarnings@SuppressWarnings 指示被該Annotation修飾的程序元素(以及該程序元素中的所有子元素)取消顯示指定的編譯器警告。@SuppressWarnings 會(huì)一直作用域該程序元素的所有子元素,例如,使用@SuppressWarnings修飾某個(gè)類取消顯示某個(gè)編譯器警告,同時(shí)又修飾該類里的某個(gè)方法取消顯示另一個(gè)編譯器警告,那么該方法將會(huì)同時(shí)取消顯示這兩個(gè)編譯器警告
Java 7的“堆污染”警告與@SafeVarargsList list = new ArrayList(); list.add(10); //添加元素時(shí)引發(fā)unchecked異常 // 下面代碼引起“未經(jīng)檢查的轉(zhuǎn)換”的警告,但編譯、運(yùn)行時(shí)完全正常 List temp = list; // ① // 但只要訪問(wèn)temp里的元素,就會(huì)引起運(yùn)行時(shí)異常 System.out.println(temp.get(0));
“堆污染”(Heap pollution):當(dāng)把一個(gè)不帶泛型的對(duì)象賦給一個(gè)帶泛型的變量時(shí),往往就會(huì)方式這種“堆污染”
Java會(huì)在定義該方法時(shí)就發(fā)出“堆污染”警告,這樣保證開(kāi)發(fā)者“更早”地注意到程序中可能存在的“漏洞”。有些時(shí)候,開(kāi)發(fā)者不希望看到這個(gè)警告,則可以使用如下三種方式來(lái)“抑制”這個(gè)警告
使用@SafeVarargs 修飾引發(fā)該警告的方法或構(gòu)造器
使用@SuppressWarnings("unchecked")修飾
編譯時(shí)使用-Xlint:varargs選項(xiàng)(很少使用)
Java 8的函數(shù)式接口與@FunctionalInterfaceJava 8規(guī)定:如果接口中只有一個(gè)抽象方法(可以包含多個(gè)默認(rèn)方法或多個(gè)static方法),該接口就是函數(shù)式接口。該注解只能夠修飾接口,不能夠修飾其他程序元素。@FunctionalInterface 只是告訴編譯器檢查這個(gè)接口,保證該接口只能包含一個(gè)抽象方法,否則就會(huì)編譯出錯(cuò)
@FunctionalInterface 只能修飾接口,不能修飾其他程序元素
JDK的元AnnotationJDK除了在java.lang下提供了5個(gè)基本的Annotation之外,還在java.lang.annotation包下提供了6個(gè)Meta Annotation,其中有5個(gè)元Annotation都用于修飾其他的Annotation定義。其中@Repeatable專門用于定義Java 8新增的重復(fù)注解
使用@Retention@Retention 只能用于修飾Annotation定義,用于指定被修飾的Annotation可以保留多長(zhǎng)時(shí)間,@Retention包含一個(gè)RetentionPolicy類型的value成員變量,所以使用@Retention時(shí)候必須為該value成員變量指定值
value成員變量的值只能是如下三個(gè):
RetentionPolicy.CLASS:編譯器將把Annotation記錄在class文件中。當(dāng)運(yùn)行java程序時(shí),JVM不可以獲取Annotation信息。這是默認(rèn)值
RetentionPolicy.RUNTIME:編譯器將把Annotation記錄在class文件中。當(dāng)運(yùn)行java程序時(shí),JVM可以獲取Annotation信息,程序也可以通過(guò)反射獲取該Annotation信息
RetentionPolicy.SOURCE:Annotation只保留在源代碼中,編譯器直接丟棄這種Annotation
// 定義下面的Testable Annotation保留到運(yùn)行時(shí) @Retention(value = RetentionPolicy.RUNTIME) public @interface Testable{} // 定義下面的Testable Annotation將被編譯器直接丟棄 @Retention(RetentionPolicy.SOURCE) public @interface Testable{}使用@Target
@Target 也只能用來(lái)修飾一個(gè)Annotation定義,它用于指定被修飾的Annotation能用于修飾哪些程序單元
其value值有如下幾個(gè):
ElementType.ANNOTATION_TYPE:指定該策略的Annotation只能修飾Annotation
ElementType.CONSTRUCTOR:指定該策略的Annotation只能修飾構(gòu)造器
ElementType.FIELD:指定該策略的Annotation只能修飾成員變量
ElementType.LOCAL_VARIABLE:指定該策略的Annotation只能修飾局部變量
ElementType.METHOD:指定該策略的Annotation只能修飾方法定義
ElementType.PACKAGE:指定該策略的Annotation只能修飾包定義
ElementType.PARAMETER:指定該策略的Annotation可以修飾參數(shù)
ElementType.TYPE:指定該策略的Annotation可以修飾類、接口(包括注釋類型)或枚舉定義
// 指定@ActionListenerFor Annotation只能修飾成員變量 @Target(ElementType.FIELD) public @interface ActionListenerFor{}使用Documented
@Documented 用于指定被該元Annotation修飾的Annotation類將被javadoc工具提取成文檔,如果定義Annotation類時(shí)候使用了@Documented 修飾,則所有使用該Annotation修飾的程序元素的API文檔中將會(huì)包含該Annotation說(shuō)明
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) // 定義Param Annotation將被javadoc工具提取 @Documented public @interface Param { long id(); String name(); String team() default "Cleveland"; } public class Person { public static void main(String[]args) { ... } // 使用@Param修飾toPerson()方法 @Param(id = 23, name = "James") public void toPerson() { ... } }使用@Inherited
@Inherited 元Annotation指定被它修飾的Annotation將具有繼承性——如果某個(gè)類使用了@Xxx注解(定義該Annotation時(shí)使用了@Inherited修飾)修飾,則其子類將自動(dòng)被@Xxx修飾
自定義Annotation 定義Annotation定義一個(gè)新的Annotation與定義一個(gè)接口類似,需要使用@interface關(guān)鍵字,例如下面定義了一個(gè)名為Param的Annotation,并在Test類中使用它:
public @interface Param { }
可以在程序的任何地方使用該Annotation,可用于修飾程序中的類、方法、變量、接口等定義。通常會(huì)把Annotation放在所有修飾符之前,另放一行
// 使用@Param修飾類定義 @Param public class Test { public static void main(String[]args) { } }
在默認(rèn)情況下,Annotation可用于修飾任何程序元素,包括類、接口、方法等。如普通方法一樣,Annotation還可以帶成員變量,Annotation的成員變量在Annotation定義中以無(wú)形參的方法形式來(lái)聲明,其方法名和返回值定義了該成員變量的名字和類型,如:
public @interface Param { long id(); String name(); String team() default "Cleveland"; }
一旦在Annotation里定義了成員變量,使用時(shí)就需要為其指定值;也可以為成員變量指定初始值(默認(rèn)值),指定成員變量的初始值可使用default關(guān)鍵字,此時(shí)可以不為這些成員變量指定值
@Param(id = 2, name = "Irving") public class Animal { public static void main(String[]args) { ... } }
根據(jù)Annotation按是否包含成員變量,Annotation分為兩類:
標(biāo)記Annotation:沒(méi)有定義成員變量的Annotation類型稱為標(biāo)記。這種Annotation僅利用自身的存在與否來(lái)為我們提供信息,例如@Override 、@Deprecated等
元數(shù)據(jù)Annotation:包含成員變量的Annotation,因?yàn)樗鼈兛梢越邮芨嗟脑獢?shù)據(jù)
提取annotation信息使用Annotation修飾了類、方法、成員變量等成員后,這些Annotation不會(huì)自己生效,必須由開(kāi)發(fā)者提供相應(yīng)的工具來(lái)提取并處理Annotation信息
AnnotatedElement接口是所有程序元素(如Class、Method、Constructor等)的父接口,所以程序通過(guò)反射獲取了某個(gè)類的AnnotatedElement對(duì)象(如Class、Method、Constructor等)之后,程序就可以調(diào)用該對(duì)象的如下幾個(gè)方法來(lái)訪問(wèn)Annotation信息
Annotation[] getAnnotations():返回該程序元素上存在的所有注解,若沒(méi)有注解,返回長(zhǎng)度為0的數(shù)組
Annotation[] getDeclaredAnnotations():返回直接修飾該程序元素的所有Annotation
boolean isAnnotationPresent(Class annotationClass) :判斷該程序元素上是否包含指定類型的注解,存在則返回true,否則返回false
// 獲取Test類的info方法里的所有注解,并將這些注解打印出來(lái) Annotation[] aArray = Class.forName("Test").getMethod("info").getAnnotations(); // 遍歷所有注解 for (Annotation an : aArray) { System.out.println(an); }
如果需要獲取某個(gè)注解里的元數(shù)據(jù),則可以將注解強(qiáng)制類型轉(zhuǎn)換成所需的主家樓下,然后通過(guò)注解對(duì)象的抽象方法來(lái)訪問(wèn)這些元數(shù)據(jù)
// 獲取tt對(duì)象的info方法所包含的所有注解 Annotation[] annotation = tt.getClass.forName().getMethod("info").getAnnotations(); // 遍歷每個(gè)注解對(duì)象 for (Annotation tag : annotation) { // 如果tag注解是MyTag1類型 if ( tag instanceof MyTag1) { System.out.println("Tag is: " + tag); // 將tag強(qiáng)制類型轉(zhuǎn)換偉MyTag1 // 輸出tag對(duì)象的method1和method2兩個(gè)成員變量的值 System.out.println("tag.name(): " + ((MyTag1)tag).method1()); System.out.println("tag.age(): " + ((MyTag1)tag).method2()); } // 如果tag注解是MyTag2類型 if ( tag instanceof MyTag2) { System.out.println("Tag is: " + tag); // 將tag強(qiáng)制類型轉(zhuǎn)換偉MyTag2 // 輸出tag對(duì)象的method1和method2兩個(gè)成員變量的值 System.out.println("tag.name(): " + ((MyTag2)tag).method1()); System.out.println("tag.age(): " + ((MyTag2)tag).method2()); } }使用Annotation的示例 e.g. One
Annotation
Testable沒(méi)有任何成員變量,僅是一個(gè)標(biāo)記Annotation,作用是標(biāo)記哪些方法是可測(cè)試的。程序通過(guò)判斷該Annotation存在與否來(lái)決定是否運(yùn)行指定方法
import java.lang.annotation.*; // 使用JDK的元數(shù)據(jù)Annotation:Retention @Retention(RetentionPolicy.RUNTIME) // 使用JDK的元數(shù)據(jù)Annotation:Target @Target(ElementType.METHOD) // 定義一個(gè)標(biāo)記注解,不包含任何成員變量,即不可傳入元數(shù)據(jù) public @interface Testable { }
@Testable 用于標(biāo)記哪些方法是可測(cè)試的,該Annotation可以作為JUnit測(cè)試框架的補(bǔ)充。在JUnit框架中,測(cè)試用例的測(cè)試方法必須以test開(kāi)頭。如果使用@Testable 注解,則可把任何方法標(biāo)記為可測(cè)試的
public class MyTest { // 使用@Testable注解指定該方法是可測(cè)試的 @Testable public static void m1() { } public static void m2() { } // 使用@Testable注解指定該方法是可測(cè)試的 @Testable public static void m3() { throw new IllegalArgumentException("參數(shù)出錯(cuò)了!"); } public static void m4() { } // 使用@Testable注解指定該方法是可測(cè)試的 @Testable public static void m5() { } public static void m6() { } // 使用@Testable注解指定該方法是可測(cè)試的 @Testable public static void m7() { throw new RuntimeException("程序業(yè)務(wù)出現(xiàn)異常!"); } public static void m8() { } }
注解處理工具分析目標(biāo)類,如果目標(biāo)類中的方法使用了@Testable 注解修飾,則通過(guò)反射來(lái)運(yùn)行該測(cè)試方法
import java.lang.reflect.*; public class ProcessorTest { public static void process(String clazz) throws ClassNotFoundException { int passed = 0; int failed = 0; // 遍歷clazz對(duì)應(yīng)的類里的所有方法 for (Method m : Class.forName(clazz).getMethods()) { // 如果該方法使用了@Testable修飾 if (m.isAnnotationPresent(Testable.class)) { try { // 調(diào)用m方法 m.invoke(null); // 測(cè)試成功,passed計(jì)數(shù)器加1 passed++; } catch (Exception ex) { System.out.println("方法" + m + "運(yùn)行失敗,異常:" + ex.getCause()); // 測(cè)試出現(xiàn)異常,failed計(jì)數(shù)器加1 failed++; } } } // 統(tǒng)計(jì)測(cè)試結(jié)果 System.out.println("共運(yùn)行了:" + (passed + failed) + "個(gè)方法,其中: " + "失敗了:" + failed + "個(gè), " + "成功了:" + passed + "個(gè)!"); } }
public class RunTests { public static void main(String[] args) throws Exception { // 處理MyTest類 ProcessorTest.process("MyTest"); } }e.g. Two
通過(guò)使用Annotation來(lái)簡(jiǎn)化事件編程,在傳統(tǒng)的事件編程中總是需要通過(guò)addActionListener()方法來(lái)為事件源綁定事件監(jiān)聽(tīng)器,下面的示例通過(guò)@ActionListenerFor來(lái)為程序中的按鈕綁定事件監(jiān)聽(tīng)器
import java.lang.annotation.*; import java.awt.event.*; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface ActionListenerFor { // 定義一個(gè)成員變量,用于設(shè)置元數(shù)據(jù) // 該listener成員變量用于保存監(jiān)聽(tīng)器實(shí)現(xiàn)類 Class extends ActionListener> listener(); }
使用@ActionListenerFor 注解來(lái)為兩個(gè)按鈕綁定事件監(jiān)聽(tīng)器
import java.awt.event.*; import javax.swing.*; public class AnnotationTest { private JFrame mainWin = new JFrame("使用注解綁定事件監(jiān)聽(tīng)器"); // 使用Annotation為ok按鈕綁定事件監(jiān)聽(tīng)器 @ActionListenerFor(listener=OkListener.class) private JButton ok = new JButton("確定"); // 使用Annotation為cancel按鈕綁定事件監(jiān)聽(tīng)器 @ActionListenerFor(listener=CancelListener.class) private JButton cancel = new JButton("取消"); public void init() { // 初始化界面的方法 JPanel jp = new JPanel(); jp.add(ok); jp.add(cancel); mainWin.add(jp); ActionListenerInstaller.processAnnotations(this); // ① mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.pack(); mainWin.setVisible(true); } public static void main(String[] args) { new AnnotationTest().init(); } } // 定義ok按鈕的事件監(jiān)聽(tīng)器實(shí)現(xiàn)類 class OkListener implements ActionListener { public void actionPerformed(ActionEvent evt) { JOptionPane.showMessageDialog(null , "單擊了確認(rèn)按鈕"); } } // 定義cancel按鈕的事件監(jiān)聽(tīng)器實(shí)現(xiàn)類 class CancelListener implements ActionListener { public void actionPerformed(ActionEvent evt) { JOptionPane.showMessageDialog(null , "單擊了取消按鈕"); } }
定義了兩個(gè)JButton按鈕,并使用@ActionListenerFor 注解為這兩個(gè)按鈕綁定了事件監(jiān)聽(tīng)器,使用@ActionListenerFor 注解時(shí)傳入了listener元數(shù)據(jù),該數(shù)據(jù)用于設(shè)定每個(gè)按鈕的監(jiān)聽(tīng)器實(shí)現(xiàn)類。程序①處代碼使用ActionListenerInstaller類來(lái)處理本程序中的注解,該處理器分析目標(biāo)對(duì)象中的所有成員變量,如果該成員變量簽使用了@ActionListenerFor修飾,則取出該Annotation中的listener元數(shù)據(jù),并根據(jù)該數(shù)據(jù)來(lái)綁定事件監(jiān)聽(tīng)器
import java.lang.reflect.*; import java.awt.event.*; import javax.swing.*; public class ActionListenerInstaller { // 處理Annotation的方法,其中obj是包含Annotation的對(duì)象 public static void processAnnotations(Object obj) { try { // 獲取obj對(duì)象的類 Class cl = obj.getClass(); // 獲取指定obj對(duì)象的所有成員變量,并遍歷每個(gè)成員變量 for (Field f : cl.getDeclaredFields()) { // 將該成員變量設(shè)置成可自由訪問(wèn)。 f.setAccessible(true); // 獲取該成員變量上ActionListenerFor類型的Annotation ActionListenerFor a = f.getAnnotation(ActionListenerFor.class); // 獲取成員變量f的值 Object fObj = f.get(obj); // 如果f是AbstractButton的實(shí)例,且a不為null if (a != null && fObj != null && fObj instanceof AbstractButton) { // 獲取a注解里的listner元數(shù)據(jù)(它是一個(gè)監(jiān)聽(tīng)器類) Class extends ActionListener> listenerClazz = a.listener(); // 使用反射來(lái)創(chuàng)建listner類的對(duì)象 ActionListener al = listenerClazz.newInstance(); AbstractButton ab = (AbstractButton)fObj; // 為ab按鈕添加事件監(jiān)聽(tīng)器 ab.addActionListener(al); } } } catch (Exception e) { e.printStackTrace(); } } }
根據(jù)@ActionListenerFor注解的元數(shù)據(jù)取得了監(jiān)聽(tīng)器實(shí)現(xiàn)類,然后通過(guò)反射來(lái)創(chuàng)建監(jiān)聽(tīng)器對(duì)象,接下來(lái)將監(jiān)聽(tīng)器對(duì)象綁定到指定的按鈕(按鈕由被@ActionListenerFor修飾的Field表示)
Java8新增的重復(fù)注解Java8允許使用多個(gè)相同類型的Annotation來(lái)修飾同一個(gè)類
@Result (name = "failure", location = "failed.jsp") @Result (name = "success", location = "succ.jsp") public Acton FooAction{...}
如果定義了@FkTag(無(wú)@Repeatable版)注解,該注解包括兩個(gè)成員變量。但該注解默認(rèn)不能作為重復(fù)注解使用,如果使用兩個(gè)以上的如下注解修飾同一個(gè)類,編譯器會(huì)報(bào)錯(cuò)
開(kāi)發(fā)重復(fù)注解需要使用@Repeatable 修飾。使用@Repeatable修飾該注解,使用@Repeatable時(shí)必須為value成員變量指定值,該成員變量的值應(yīng)該是一個(gè)“容器”注解——該容器注解可以包含多個(gè)@FkTag
import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Repeatable(FkTags.class) public @interface FkTag { // 為該注解定義2個(gè)成員變量 String name() default "NBA球員"; int number(); }
“容器”注解可包含多個(gè)@FkTag,因此需要定義如下的“容器”注解
import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) // ① @Target(ElementType.TYPE) public @interface FkTags { // 定義value成員變量,該成員變量可接受多個(gè)@FkTag注解 FkTag[] value(); // ② }
代碼①指定了@FkTags 注解信息可保留到運(yùn)行時(shí),這是必需的,因?yàn)锧FkTag 注解信息需要保留到運(yùn)行時(shí),如果@FkTags 注解只能保留到源代碼級(jí)別或類文件,將會(huì)導(dǎo)致@FkTags 的保留期小于@FkTag 的保留期,如果程序?qū)⒍鄠€(gè)@FkTag注解放入@FkTags中,若JVM丟棄了@FkTags注解,自然也就丟棄了@FkTag的信息
代碼②定義了一個(gè)FkTag[]類型的value成員變量,這意味著@FkTags 注解的value成員變量可接受多個(gè)@FkTags 注解可作為@FkTag 的容器
“容器”注解的保留期必須必它所包含的注解的保留期更長(zhǎng),否則編譯器會(huì)報(bào)錯(cuò)
傳統(tǒng)代碼使用該注解
@FkTags({@FkTag(number = 23), @FkTag(name = "Westbrooks", number = 0)})
由于@FkTags是重復(fù)注解,因此可直接使用兩個(gè)@FkTag注解,系統(tǒng)依然將兩個(gè)@FkTag注解作為@FkTags的values成員變量的數(shù)組元素
@FkTag(number = 23) @FkTag(name = "Westbrooks", number = 0)
重復(fù)注解是一種簡(jiǎn)化寫法,這種簡(jiǎn)化寫法是一種假象:多個(gè)重復(fù)注解會(huì)被作為“容器”注解的value成員變量的數(shù)組元素
@FkTag(number = 23) @FkTag(name = "Westbrooks", number = 0) public class FkTagTest { public static void main(String[] args) { Classclazz = FkTagTest.class; /* 使用Java 8新增的getDeclaredAnnotationsByType()方法獲取 修飾FkTagTest類的多個(gè)@FkTag注解 */ FkTag[] tags = clazz.getDeclaredAnnotationsByType(FkTag.class); // 遍歷修飾FkTagTest類的多個(gè)@FkTag注解 for(FkTag tag : tags) { System.out.println(tag.name() + "-->" + tag.age()); } } }
運(yùn)行結(jié)果:
NBA球員-->23 Westbrooks-->0 @FkTags(value=[@FkTag(name=NBA球員, age=23), @FkTag(name=Westbrooks, age=0)])Java8新增的Type Annotation
Java8為ElementType枚舉增加了TYPE_PARAMETER、TYPE_USE兩個(gè)枚舉值,允許定義枚舉時(shí)使用@Target(ElementType.TYPE_USE)修飾,這種注解稱為Type Annotation(類型注解),Type Annotation可用在任何用到類型的地方
允許在如下位置使用Type Annotation
創(chuàng)建對(duì)象(用new關(guān)鍵字創(chuàng)建)
類型轉(zhuǎn)換
使用implements實(shí)現(xiàn)接口
使用throws聲明拋出異常
import java.util.*; import java.io.*; import javax.swing.*; import java.lang.annotation.*; // 定義一個(gè)簡(jiǎn)單的Type Annotation,不帶任何成員變量 @Target(ElementType.TYPE_USE) @interface NotNull{} // 定義類時(shí)使用Type Annotation @NotNull public class TypeAnnotationTest implements @NotNull /* implements時(shí)使用Type Annotation */ Serializable { // 方法形參中使用Type Annotation public static void main(@NotNull String[] args) // throws時(shí)使用Type Annotation throws @NotNull FileNotFoundException { Object obj = "fkjava.org"; // 強(qiáng)制類型轉(zhuǎn)換時(shí)使用Type Annotation String str = (@NotNull String)obj; // 創(chuàng)建對(duì)象時(shí)使用Type Annotation Object win = new @NotNull JFrame("俄克拉荷馬雷霆"); } // 泛型中使用Type Annotation public void foo(List<@NotNull String> info){} }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/66530.html
摘要:定義注解,也叫元數(shù)據(jù)。它可以聲明在包類字段方法局部變量方法參數(shù)等的前面,用來(lái)對(duì)這些元素進(jìn)行說(shuō)明,注釋。方法返回該程序元素上存在的所有注解。與此接口中的其他方法不同,該方法將忽略繼承的注釋。 定義: 注解(Annotation),也叫元數(shù)據(jù)。一種代碼級(jí)別的說(shuō)明。它是JDK5.0及以后版本引入的一個(gè)特性,與類、接口、枚舉是在同一個(gè)層次。 它可以聲明在包、類、字段、方法、局部變量、方法參數(shù)等...
摘要:注解全解析什么是注解注解有什么作用注解是怎么干活的如何自定義注解什么是注解注解即元數(shù)據(jù),一種描述數(shù)據(jù)的數(shù)據(jù),可以說(shuō)注解就是源代碼的元數(shù)據(jù)是一種應(yīng)用于類方法參數(shù)變量構(gòu)造器及包聲明中的特殊修飾符不能影響程序代碼的運(yùn)行,無(wú)論增加刪除注解,代碼都始 注解全解析 什么是注解? 注解有什么作用? 注解是怎么干活的? 如何自定義注解? 什么是注解 注解即元數(shù)據(jù),一種描述數(shù)據(jù)的數(shù)據(jù),可以說(shuō)注解就...
摘要:注解提供了一種安全的類似注釋的機(jī)制,用來(lái)將任何的信息或元數(shù)據(jù)與程序元素類方法成員變量等進(jìn)行關(guān)聯(lián)。為程序的元素類方法成員變量加上更直觀更明了的說(shuō)明,這些說(shuō)明與程序的業(yè)務(wù)邏輯無(wú)關(guān),并且提供給指定的工具或框架使用。 什么是注解? Annotation 是 Java5 之后開(kāi)始引入的新特性,中文為注解。注解提供了一種安全的類似注釋的機(jī)制,用來(lái)將任何的信息或元數(shù)據(jù)(metadata)與程序元素(...
摘要:的在日常開(kāi)發(fā),特別是開(kāi)發(fā)中使用廣泛,各種框架,測(cè)試框架多多少少都會(huì)引入一些注解。的功能是作用于程序元數(shù)據(jù)的特殊類型。而在編譯期使用注解則需要特殊的工具,本文不討論。可以看到通過(guò)類中的反射方法獲取到了這個(gè)類的注解以及其方法的注解。 Java的Annotation在日常開(kāi)發(fā),特別是java web開(kāi)發(fā)中使用廣泛,各種web框架,測(cè)試框架多多少少都會(huì)引入一些注解。若對(duì)java注解有一個(gè)全面深...
摘要:另一個(gè)很重要的因素是定義了一種標(biāo)準(zhǔn)的描述元數(shù)據(jù)的方式。對(duì)于注解,它的用戶就是虛擬機(jī),工作在字節(jié)碼層面,在編譯階段進(jìn)行檢查,其處理機(jī)制主要是內(nèi)部處理。 什么是注解 用一個(gè)詞就可以描述注解,那就是元數(shù)據(jù),即一種描述數(shù)據(jù)的數(shù)據(jù)。所以,可以說(shuō)注解就是源代碼的元數(shù)據(jù)。比如,下面這段代碼: @Override public String toString() { return This is St...
閱讀 637·2021-11-22 15:32
閱讀 2725·2021-11-19 09:40
閱讀 2320·2021-11-17 09:33
閱讀 1277·2021-11-15 11:36
閱讀 1874·2021-10-11 10:59
閱讀 1485·2019-08-29 16:41
閱讀 1788·2019-08-29 13:45
閱讀 2156·2019-08-26 13:36