枚舉的使用
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(已確認(rèn))Fulfilled(已配貨)、 線程狀態(tài):創(chuàng)建、就緒、運(yùn)行、阻塞、死亡 當(dāng)需要定義一組常量時,強(qiáng)烈建議使用枚舉類 枚舉類的實(shí)現(xiàn) JDK1.5之前需要自定義枚舉類 JDK 1.5 新增的 enum 關(guān)鍵字用于定義枚舉類 若枚舉只有一個對象, 則可以作為一種單例模式的實(shí)現(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)建枚舉類的實(shí)例。聲明為:public static final 對象如果有實(shí)例變量,應(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 定義的枚舉類默認(rèn)繼承了 java.lang.Enum 類,因此不能再繼承其他類 枚舉類的構(gòu)造器只能使用 private 權(quán)限修飾符 枚舉類的所有實(shí)例必須在枚舉類中顯式列出(, 分隔 ; 結(jié)尾)。列出的實(shí)例系統(tǒng)會自動添加 public static final 修飾 必須在枚舉類的第一行聲明枚舉類對象 JDK 1.5 中可以在 switch 表達(dá)式中使用 Enum 定義的枚舉類的對象作為表達(dá)式, 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 )類的主要方法protected Enum(String name,int ordinal)唯一的構(gòu)造函數(shù)。 程序員無法調(diào)用此構(gòu)造函數(shù)。
它由編譯器響應(yīng)枚舉類型聲明發(fā)出的代碼使用。
protected Object clone() 枚舉類型不能被 Clone.為了防止子類實(shí)現(xiàn)克隆方法,
Enum實(shí)現(xiàn)了一個拋出CloneNotSupportedException異常的不變 Clone()。
int compareTo(E o) 枚舉類型實(shí)現(xiàn)了 Comparable 接口,這樣可用比較兩個枚舉常量的大小(按照聲明的順序排序)。
boolean equals(Object other) 在枚舉類型中可用直接使用 "=="來比較兩個枚舉常量是否相等。
Enum提供這個 equals()方法,也是直接使用 "=="實(shí)現(xiàn)的.它的存在是為了在 set,list和map中使用.注意equals()是不可變的.
protected void finalize() 枚舉類不能有finalize方法。
ClassgetDeclaringClass() 得到枚舉常量所屬枚舉類型的 Class對象.可用用它來判斷兩個枚舉常量是否屬于同一個枚舉類型。
int hashCode() Enum實(shí)現(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)的枚舉類對象.要求字符串必須是枚舉對象的 "名字".如果不是,會有運(yùn)行時異常
IllegalArgumentException.
toString(); 返回當(dāng)前枚舉對象常量的名稱 Methods inherited from class java.lang.Object : getClass, notify, notifyAll, wait, wait, wait
5. 實(shí)現(xiàn)接口的枚舉類和普通 Java 類一樣,枚舉類可以實(shí)現(xiàn)一個或多個接口 若每個枚舉值在調(diào)用實(shí)現(xiàn)的接口方法呈現(xiàn)相同的行為方式,則只要統(tǒng)一實(shí)現(xiàn)該方法即可。 若需要每個枚舉值在調(diào)用實(shí)現(xiàn)的接口方法呈現(xiàn)出不同的行為方式,則可以讓每個枚舉值分別來實(shí)現(xiàn)該方法
//情況1: 實(shí)現(xiàn)接口,在 enum類中實(shí)現(xiàn)抽象方法
//情況2: 讓枚舉的對象分別實(shí)現(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 其實(shí)就是代碼里的特殊標(biāo)記, 這些標(biāo)記可以在編譯, 類加載, 運(yùn)行時被讀取, 并執(zhí)行相應(yīng)的處理。通過使用 Annotation, 程序員可以在不改變原有邏輯的情況下, 在源文件中嵌入一些補(bǔ)充信息。代碼分析工具、開發(fā)工具和部署工具可以通過這些補(bǔ)充信息進(jìn)行驗(yàn)證或者進(jìn)行部署。 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 對方法可能拋出的異常進(jìn)行說明,如果方法沒有用throws顯式拋出的異常就不能寫其中 @param @return 和@exception 這三個標(biāo)記都是只用于方法的。 @param的格式要求:@param 形參名形參類型 形參說明 @return 的格式要求:@return 返回值類型返回值說明 @exception的格式要求:@exception 異常類型異常說明 @param和@exception可以并列多個

示例二:在編譯時進(jìn)行格式檢查(JDK內(nèi)置的三個基本注解) @Override: 限定重寫父類方法, 該注解只能用于方法 @Deprecated: 用于表示所修飾的元素(類, 方法等)已過時。通常是因?yàn)樗揎椀慕Y(jié)構(gòu)危險或存在更好的選擇 @SuppressWarnings: 抑制編譯器警告
 示例三:跟蹤代碼依賴性,實(shí)現(xiàn)替代配置文件功能 Servlet3.0提供了注解(annotation),使得不再需要在web.xml文件中進(jìn)行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ù)值,除非它有默認(rèn)值。格式是“參數(shù)名 = 參數(shù)值”,如果只有一個參數(shù)成員,且名稱為value,可以省略“value=” 沒有成員定義的 Annotation 稱為標(biāo)記; 包含成員變量的 Annotation 稱為元數(shù)據(jù)Annotation 注意:自定義注解必須配上注解的信息處理流程(反射)才有意義。
//1. 注解聲明為 @interface
public @interface MyAnnotation {
//2. 內(nèi)部定義成員,通常使用 value表示
//3. 可用指定成員的默認(rèn)值,使用 default定義
//4. 如果自定義注解沒有成員,表明是一個表示作用
String vale() default "hello";
}
//5. 如果注解有成員,在使用注解時,需要指明成員的值.
//@MyAnnotation(vale = "hello")
@MyAnnotation
class test {
public static void main(String[] args) {
}
} 4. JDK中的元注解JDK 的元Annotation(對現(xiàn)有的注解進(jì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)運(yùn)行 Java 程序時, JVM不會保留注解。 這是默認(rèn)值 RetentionPolicy.RUNTIME:在運(yùn)行時有效(即運(yùn)行時保留),當(dāng)運(yùn)行 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 工具提取成文檔。默認(rèn)情況下,javadoc是不包括注解的。 定義為Documented的注解必須設(shè)置Retention值為RUNTIME。 @Inherited: 被它修飾的 Annotation 將具有繼承性。如果某個類使用了被@Inherited 修飾的 Annotation, 則其子類將自動具有該注解。 比如:如果把標(biāo)有 @Inherited注解的自定義的注解標(biāo)注在類級別上,子類則可以繼承父類類級別的注解 實(shí)際應(yīng)用中,使用較少
5. 利用反射獲取注解信息JDK 5.0 在 java.lang.reflect 包下新增了 AnnotatedElement 接口, 該接口代表程序中可以接受注解的程序元素 當(dāng)一個Annotation 類型被定義為運(yùn)行時Annotation 后, 該注解才是運(yùn)行時可見, 當(dāng) class 文件被載入時保存在 class 文件中的Annotation 才會被虛擬機(jī)讀取 程序可以調(diào)用AnnotatedElement對象的如下方法來訪問Annotation 信息

6. JDK 8中注解的新特性Java 8對注解處理提供了兩點(diǎn)改進(jìn):可重復(fù)的注解及可用于類型的注解。此外,反射也得到了加強(qiáng),在Java8中能夠得到方法參數(shù)的名稱。這會簡化標(biāo)注在方法參數(shù)上的注解。 可重復(fù)注解 //1. 注解聲明為 @interface
public @interface MyAnnotation {
//2. 內(nèi)部定義成員,通常使用 value表示
//3. 可用指定成員的默認(rèn)值,使用 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. 可用指定成員的默認(rèn)值,使用 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 表示該注解能寫在使用類型的任何語句中。
|