編程語言枚舉與注解枚舉的使用
1. 枚舉簡介
類的對象只有有限個,確定的。舉例如下:
星期:Monday(星期一)、......、Sunday(星期天)
性別:Man(男)、Woman(女)
季節(jié):Spring(春節(jié))......Winter(冬天)
支付方式:Cash(現(xiàn)金)、WeChatPay(微信)、Alipay(支付寶)、BankCard(銀行卡)、CreditCard(信用卡)
就職狀態(tài):Busy、Free、Vocation、Dimission
訂單狀態(tài):Nonpayment(未付款)、Paid(已付款)、Delivered(已發(fā)貨)、 Return(退貨)、Checked(已確認)Fulfilled(已配貨)、
線程狀態(tài):創(chuàng)建、就緒、運行、阻塞、死亡
當(dāng)需要定義一組常量時,強烈建議使用枚舉類
枚舉類的實現(xiàn)
JDK1.5之前需要自定義枚舉類
JDK 1.5 新增的 enum 關(guān)鍵字用于定義枚舉類
若枚舉只有一個對象, 則可以作為一種單例模式的實現(xiàn)方式。
枚舉類的屬性
枚舉類對象的屬性不應(yīng)允許被改動, 所以應(yīng)該使用 private final 修飾
枚舉類的使用 private final 修飾的屬性應(yīng)該在構(gòu)造器中為其賦值
若枚舉類顯式的定義了帶參數(shù)的構(gòu)造器, 則在列出枚舉值時也必須對應(yīng)的傳入?yún)?shù)
2. 如何自定義枚舉類(jdk 5.0之前)
私有化類的構(gòu)造器,保證不能在類的外部創(chuàng)建其對象
在類的內(nèi)部創(chuàng)建枚舉類的實例。聲明為:public static final
對象如果有實例變量,應(yīng)該聲明為 private final,并在構(gòu)造器中初始化
其他訴求:獲取枚舉對象的屬性
//自定義枚舉類class Season { //1. 聲明 Season 屬性 private final String seasonName; private final String seasonDesc; //2. 私有化類的構(gòu)造器,并給對象屬性賦值 private Season(String seasonName, String seasonDesc) { this.seasonName = seasonName; this.seasonDesc = seasonDesc; } //3. 提供當(dāng)前枚舉類的多個對象 public static final Season SPRING = new Season("春天", "春暖花開"); public static final Season SUMMER = new Season("夏天", "夏日炎炎"); public static final Season AUTUMN = new Season("秋天", "秋高氣爽"); public static final Season WINTER = new Season("冬天", "冰天雪地"); //4. 其他訴求:獲取枚舉對象的屬性 public String getSeasonName() { return seasonName; } public String getSeasonDesc() { return seasonDesc; } @Override public String toString() { return "Season{" + "seasonName='" + seasonName + '\'' + ", seasonDesc='" + seasonDesc + '\'' + '}'; }}public class SeasonTest { public static void main(String[] args) { System.out.println(Season.AUTUMN);//Season{seasonName='秋天', seasonDesc='秋高氣爽'} }}3. 如何使用關(guān)鍵字(jdk 5.0) enum定義枚舉類
使用說明
使用 enum 定義的枚舉類默認繼承了 java.lang.Enum類,因此不能再繼承其他類
枚舉類的構(gòu)造器只能使用 private 權(quán)限修飾符
枚舉類的所有實例必須在枚舉類中顯式列出(, 分隔 ; 結(jié)尾)。列出的實例系統(tǒng)會自動添加 public static final 修飾
必須在枚舉類的第一行聲明枚舉類對象
JDK 1.5 中可以在 switch 表達式中使用 Enum 定義的枚舉類的對象作為表達式, case 子句可以直接使用枚舉值的名字, 無需添加枚舉類作為限定。
使用步驟
提供當(dāng)前枚舉類的多個對象 : 多個對象之間用 逗號 隔開,末尾對象 分號 結(jié)束
聲明 自定義枚舉類的 屬性
私有化類的構(gòu)造器,并給對象屬性賦值
其他訴求:獲取枚舉對象的屬性
//自定義枚舉類enum Season1 { //1. 提供當(dāng)前枚舉類的多個對象 : 多個對象之間用 逗號 隔開,末尾對象 分號 結(jié)束 SPRING("春天", "春暖花開"), SUMMER("夏天", "夏日炎炎"), AUTUMN("秋天", "秋高氣爽"), WINTER("冬天", "冰天雪地"); //2. 聲明 Season1 屬性 private final String seasonName; private final String seasonDesc; //3. 私有化類的構(gòu)造器,并給對象屬性賦值 private Season1(String seasonName, String seasonDesc) { this.seasonName = seasonName; this.seasonDesc = seasonDesc; } //4. 其他訴求:獲取枚舉對象的屬性 public String getSeasonDesc() { return seasonDesc; } public String getSeasonName() { return seasonName; }}public class SeasonTest1 { public static void main(String[] args) { System.out.println(Season1.WINTER);//WINTER System.out.println(Season1.class.getSuperclass());//class java.lang.Enum }}4. Enum(jdk 1.5 )類的主要方法
java.lang public abstract class Enum<e extends="" enum> extends Object implements Comparable, Serializable
protected Enum(String name,int ordinal)唯一的構(gòu)造函數(shù)。 程序員無法調(diào)用此構(gòu)造函數(shù)。 它由編譯器響應(yīng)枚舉類型聲明發(fā)出的代碼使用。protected Object clone() 枚舉類型不能被 Clone.為了防止子類實現(xiàn)克隆方法, Enum實現(xiàn)了一個拋出CloneNotSupportedException異常的不變 Clone()。 int compareTo(E o) 枚舉類型實現(xiàn)了 Comparable 接口,這樣可用比較兩個枚舉常量的大小(按照聲明的順序排序)。 boolean equals(Object other) 在枚舉類型中可用直接使用 "=="來比較兩個枚舉常量是否相等。 Enum提供這個 equals()方法,也是直接使用 "=="實現(xiàn)的.它的存在是為了在 set,list和map中使用.注意equals()是不可變的. protected void finalize() 枚舉類不能有finalize方法。 ClassgetDeclaringClass() 得到枚舉常量所屬枚舉類型的 Class對象.可用用它來判斷兩個枚舉常量是否屬于同一個枚舉類型。 int hashCode() Enum實現(xiàn)了 hashCode()來和 equals()保持一致.它也是不可變的。 String name() 返回此枚舉常量的名稱,與其枚舉聲明中聲明的完全相同。 int ordinal() 返回此枚舉常數(shù)的序數(shù)(其枚舉聲明中的位置,其中初始常數(shù)的序數(shù)為零)。 String toString() 得到當(dāng)前枚舉常量的名稱。你可以通過從寫這個方法來使得到的結(jié)果更易讀. static<t extends="" enum> T valueOf(ClassenumType, String name) 傳遞枚舉類型的 Class對象和枚舉常量名稱 給靜態(tài)方法 valueOf,會得到與參數(shù)匹配的枚舉常量。values(); 返回枚舉類型的對象數(shù)組.該方法可用很方便的遍歷所有的枚舉值.valueOf(String str); 可用把一個字符串轉(zhuǎn)為對應(yīng)的枚舉類對象.要求字符串必須是枚舉對象的 "名字".如果不是,會有運行時異常 IllegalArgumentException.toString(); 返回當(dāng)前枚舉對象常量的名稱
Methods inherited from class java.lang.Object : getClass, notify, notifyAll, wait, wait, wait
5. 實現(xiàn)接口的枚舉類
和普通 Java 類一樣,枚舉類可以實現(xiàn)一個或多個接口
若每個枚舉值在調(diào)用實現(xiàn)的接口方法呈現(xiàn)相同的行為方式,則只要統(tǒng)一實現(xiàn)該方法即可。
若需要每個枚舉值在調(diào)用實現(xiàn)的接口方法呈現(xiàn)出不同的行為方式,則可以讓每個枚舉值分別來實現(xiàn)該方法
//情況1: 實現(xiàn)接口,在 enum類中實現(xiàn)抽象方法//情況2: 讓枚舉的對象分別實現(xiàn)接口中的抽象方法interface Info { void show();}//自定義枚舉類enum Season1 implements Info { //1. 提供當(dāng)前枚舉類的多個對象 : 多個對象之間用 逗號 隔開,末尾對象 分號 結(jié)束 SPRING("春天", "春暖花開"){ @Override public void show() { System.out.println("春天在哪里"); } }, SUMMER("夏天", "夏日炎炎"){ @Override public void show() { System.out.println("寧夏"); } }, AUTUMN("秋天", "秋高氣爽"){ @Override public void show() { System.out.println("秋天不回來"); } }, WINTER("冬天", "冰天雪地"){ @Override public void show() { System.out.println("大約在冬季"); } }; //2. 聲明 Season1 屬性 private final String seasonName; private final String seasonDesc; //3. 私有化類的構(gòu)造器,并給對象屬性賦值 private Season1(String seasonName, String seasonDesc) { this.seasonName = seasonName; this.seasonDesc = seasonDesc; } //5. 其他訴求:獲取枚舉對象的屬性 public String getSeasonDesc() { return seasonDesc; } public String getSeasonName() { return seasonName; } /*@Override public void show() { System.out.println("這是一個季節(jié)"); }*/}//調(diào)用 :Season1.AUTUMN.show();注解的使用
1. 注解(Annotation)概述
從 JDK 5.0 開始, Java 增加了對元數(shù)據(jù)(MetaData) 的支持, 也就是Annotation(注解)
Annotation 其實就是代碼里的特殊標(biāo)記, 這些標(biāo)記可以在編譯, 類加載, 運行時被讀取, 并執(zhí)行相應(yīng)的處理。通過使用 Annotation, 程序員可以在不改變原有邏輯的情況下, 在源文件中嵌入一些補充信息。代碼分析工具、開發(fā)工具和部署工具可以通過這些補充信息進行驗證或者進行部署。
Annotation 可以像修飾符一樣被使用, 可用于修飾包,類, 構(gòu)造器, 方法, 成員變量, 參數(shù), 局部變量的聲明, 這些信息被保存在 Annotation的 “name=value” 對中。
在JavaSE中,注解的使用目的比較簡單,例如標(biāo)記過時的功能,忽略警告等。在JavaEE/Android中注解占據(jù)了更重要的角色,例如用來配置應(yīng)用程序的任何切面,代替 JavaEE舊版中所遺留的繁冗代碼和 XML配置等。
未來的開發(fā)模式都是基于注解的,JPA是基于注解的,Spring2.5以上都是基于注解的,Hibernate3.x以后也是基于注解的,現(xiàn)在的Struts2有一部分也是基于注解的了,注解是一種趨勢,一定程度上可以說:框架 = 注解 + 反射 + 設(shè)計模式。
2. 常見的Annotation示例
使用 Annotation 時要在其前面增加 @ 符號, 并把該Annotation 當(dāng)成一個修飾符使用。用于修飾它支持的程序元素
示例一:生成文檔相關(guān)的注解
@author 標(biāo)明開發(fā)該類模塊的作者,多個作者之間使用,分割
@version 標(biāo)明該類模塊的版本
@see 參考轉(zhuǎn)向,也就是相關(guān)主題
@since 從哪個版本開始增加的
@param 對方法中某參數(shù)的說明,如果沒有參數(shù)就不能寫
@return 對方法返回值的說明,如果方法的返回值類型是void就不能寫
@exception 對方法可能拋出的異常進行說明,如果方法沒有用throws顯式拋出的異常就不能寫其中
@param @return 和@exception 這三個標(biāo)記都是只用于方法的。 @param的格式要求:@param 形參名形參類型 形參說明
@return 的格式要求:@return 返回值類型返回值說明
@exception的格式要求:@exception 異常類型異常說明
@param和@exception可以并列多個
示例二:在編譯時進行格式檢查(JDK內(nèi)置的三個基本注解)
@Override: 限定重寫父類方法, 該注解只能用于方法
@Deprecated: 用于表示所修飾的元素(類, 方法等)已過時。通常是因為所修飾的結(jié)構(gòu)危險或存在更好的選擇
@SuppressWarnings: 抑制編譯器警告
示例三:跟蹤代碼依賴性,實現(xiàn)替代配置文件功能
Servlet3.0提供了注解(annotation),使得不再需要在web.xml文件中進行Servlet的部署。
3. 自定義Annotation
定義新的Annotation 類型使用@interface 關(guān)鍵字
自定義注解自動繼承了java.lang.annotation.Annotation接口
Annotation 的成員變量在 Annotation 定義中以無參數(shù)方法的形式來聲明。其方法名和返回值定義了該成員的名字和類型。我們稱為配置參數(shù)。類型只能是八種基本數(shù)據(jù)類型、String類型、Class類型、enum類型、Annotation類型、以上所有類型的數(shù)組。
可以在定義 Annotation 的成員變量時為其指定初始值, 指定成員變量的初始值可使用default 關(guān)鍵字
如果只有一個參數(shù)成員,建議使用參數(shù)名為value
如果定義的注解含有配置參數(shù),那么使用時必須指定參數(shù)值,除非它有默認值。格式是“參數(shù)名 = 參數(shù)值”,如果只有一個參數(shù)成員,且名稱為value,可以省略“value=”
沒有成員定義的 Annotation 稱為標(biāo)記; 包含成員變量的 Annotation 稱為元數(shù)據(jù)Annotation
注意:自定義注解必須配上注解的信息處理流程(反射)才有意義。
//1. 注解聲明為 @interfacepublic @interface MyAnnotation { //2. 內(nèi)部定義成員,通常使用 value表示 //3. 可用指定成員的默認值,使用 default定義 //4. 如果自定義注解沒有成員,表明是一個表示作用 String vale() default "hello";}//5. 如果注解有成員,在使用注解時,需要指明成員的值.//@MyAnnotation(vale = "hello")@MyAnnotationclass test { public static void main(String[] args) { }}4. JDK中的元注解
JDK 的元Annotation(對現(xiàn)有的注解進行說明的注解) 用于修飾其他Annotation 定義
JDK5.0提供了4個標(biāo)準(zhǔn)的meta-annotation類型,分別是:
Retention 指定所修飾的 Annotation的聲明周期
Target 用于指定被修飾的 Annotation能用于修飾那些程序元素
Documented 所修飾的注解被 javadoc解析時,被保留下來
Inherited 被它修飾的 Annotation將具有繼承性(通過反射獲取獲取注解信息)
元數(shù)據(jù)的理解:
String name = “atguigu”;
@Retention: 只能用于修飾一個 Annotation 定義, 用于指定該 Annotation 的生命周期, @Rentention 包含一個 RetentionPolicy 類型的成員變量, 使用@Rentention 時必須為該 value 成員變量指定值:
RetentionPolicy.SOURCE:在源文件中有效(即源文件保留),編譯器直接丟棄這種策略的注釋
RetentionPolicy.CLASS:在class文件中有效(即class保留) , 當(dāng)運行 Java 程序時, JVM不會保留注解。 這是默認值
RetentionPolicy.RUNTIME:在運行時有效(即運行時保留),當(dāng)運行 Java 程序時, JVM 會保留注釋。程序可以通過反射獲取該注釋。
@Target: 用于修飾Annotation 定義, 用于指定被修飾的Annotation 能用于修飾哪些程序元素。 @Target 也包含一個名為 value 的成員變量。
取值(element type)描述
constructor用于描述構(gòu)造器
field用于描述域
local_varibable用于描述局部變量
method用于描述方法
package用于描述包
parameter用于描述參數(shù)
type用于描述類,接口(包括注解類型)或者 enum聲明
@Documented: 用于指定被該元Annotation 修飾的Annotation 類將被javadoc 工具提取成文檔。默認情況下,javadoc是不包括注解的。
定義為Documented的注解必須設(shè)置Retention值為RUNTIME。
@Inherited: 被它修飾的 Annotation 將具有繼承性。如果某個類使用了被@Inherited 修飾的 Annotation, 則其子類將自動具有該注解。
比如:如果把標(biāo)有 @Inherited注解的自定義的注解標(biāo)注在類級別上,子類則可以繼承父類類級別的注解
實際應(yīng)用中,使用較少
5. 利用反射獲取注解信息
JDK 5.0 在 java.lang.reflect 包下新增了 AnnotatedElement 接口, 該接口代表程序中可以接受注解的程序元素
當(dāng)一個Annotation 類型被定義為運行時Annotation 后, 該注解才是運行時可見, 當(dāng) class 文件被載入時保存在 class 文件中的Annotation 才會被虛擬機讀取
程序可以調(diào)用AnnotatedElement對象的如下方法來訪問Annotation 信息
6. JDK 8中注解的新特性
Java 8對注解處理提供了兩點改進:可重復(fù)的注解及可用于類型的注解。此外,反射也得到了加強,在Java8中能夠得到方法參數(shù)的名稱。這會簡化標(biāo)注在方法參數(shù)上的注解。
可重復(fù)注解
//1. 注解聲明為 @interfacepublic @interface MyAnnotation {//2. 內(nèi)部定義成員,通常使用 value表示//3. 可用指定成員的默認值,使用 default定義//4. 如果自定義注解沒有成員,表明是一個表示作用String vale() default "hello";}//5. 如果注解有成員,在使用注解時,需要指明成員的值.@interface MyAnnotations {MyAnnotation[] value();}@MyAnnotations({@MyAnnotation(vale = "b"), @MyAnnotation(vale = "a")})class Test {}
jdk8
//1. 注解聲明為 @interface@Inherited@Repeatable(MyAnnotations.class)public @interface MyAnnotation {//2. 內(nèi)部定義成員,通常使用 value表示//3. 可用指定成員的默認值,使用 default定義//4. 如果自定義注解沒有成員,表明是一個表示作用String vale() default "hello";}//5. 如果注解有成員,在使用注解時,需要指明成員的值.@interface MyAnnotations {MyAnnotation[] value();}@MyAnnotation(vale = "123")@MyAnnotation(vale = "abc")class Test {}
在 MyAnnotation 上聲明 @Repeatable,成員值為 MyAnnotations.class
MyAnnotation的 Target和 Retention和 MyAnnotations相同.
jdk8 之前的寫法
類型注解
class TestTypeDefine<@TypeDefine() U> {private U u;public <@TypeDefine() T> void test(T t) {}}@Target({ElementType.TYPE_PARAMETER})@interface TypeDefine {}
JDK1.8之后,關(guān)于元注解 @Target的參數(shù)類型 ElementType 枚舉值多了兩個:TYPE_PARAMETER,TYPE_USE。
在Java 8之前,注解只能是在聲明的地方所使用,Java8開始,注解可以應(yīng)用在任何地方。
ElementType.TYPE_PARAMETER 表示該注解能寫在類型變量的聲明語句中(如:泛型聲明)。
ElementType.TYPE_USE 表示該注解能寫在使用類型的任何語句中。
www.bdsoba.comwww.awaedu.comwww.zuowenge.cn