|
JDK1.5引入了新的類型——枚舉。在 Java 中它雖然算個“小”功能,卻給我的開發(fā)帶來了“大”方便。 大師兄我又加上自己的理解,來幫助各位理解一下。 用法一:常量在JDK1.5 之前,我們定義常量都是: public static fianl.... 。現(xiàn)在好了,有了枚舉,可以把相關(guān)的常量分組到一個枚舉類型里,而且枚舉提供了比常量更多的方法。 - public enum Color {
- RED, GREEN, BLANK, YELLOW
- }
用法二:switchJDK1.6之前的switch語句只支持int,char,enum類型,使用枚舉,能讓我們的代碼可讀性更強(qiáng)。 - enum Signal {
- GREEN, YELLOW, RED
- }
- public class TrafficLight {
- Signal color = Signal.RED;
- public void change() {
- switch (color) {
- case RED:
- color = Signal.GREEN;
- break;
- case YELLOW:
- color = Signal.RED;
- break;
- case GREEN:
- color = Signal.YELLOW;
- break;
- }
- }
- }
用法三:向枚舉中添加新方法如果打算自定義自己的方法,那么必須在enum實例序列的最后添加一個分號。而且 Java 要求必須先定義 enum 實例。 - public enum Color {
- RED("紅色", 1), GREEN("綠色", 2), BLANK("白色", 3), YELLO("黃色", 4);
- // 成員變量
- private String name;
- private int index;
- // 構(gòu)造方法
- private Color(String name, int index) {
- this.name = name;
- this.index = index;
- }
- // 普通方法
- public static String getName(int index) {
- for (Color c : Color.values()) {
- if (c.getIndex() == index) {
- return c.name;
- }
- }
- return null;
- }
- // get set 方法
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getIndex() {
- return index;
- }
- public void setIndex(int index) {
- this.index = index;
- }
- }
用法四:覆蓋枚舉的方法下面給出一個toString()方法覆蓋的例子。 - public enum Color {
- RED("紅色", 1), GREEN("綠色", 2), BLANK("白色", 3), YELLO("黃色", 4);
- // 成員變量
- private String name;
- private int index;
- // 構(gòu)造方法
- private Color(String name, int index) {
- this.name = name;
- this.index = index;
- }
- //覆蓋方法
- @Override
- public String toString() {
- return this.index+"_"+this.name;
- }
- }
用法五:實現(xiàn)接口所有的枚舉都繼承自java.lang.Enum類。由于Java 不支持多繼承,所以枚舉對象不能再繼承其他類。 - public interface Behaviour {
- void print();
- String getInfo();
- }
- public enum Color implements Behaviour{
- RED("紅色", 1), GREEN("綠色", 2), BLANK("白色", 3), YELLO("黃色", 4);
- // 成員變量
- private String name;
- private int index;
- // 構(gòu)造方法
- private Color(String name, int index) {
- this.name = name;
- this.index = index;
- }
- //接口方法
- @Override
- public String getInfo() {
- return this.name;
- }
- //接口方法
- @Override
- public void print() {
- System.out.println(this.index+":"+this.name);
- }
- }
用法六:使用接口組織枚舉 Java代碼 - public interface Food {
- enum Coffee implements Food{
- BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO
- }
- enum Dessert implements Food{
- FRUIT, CAKE, GELATO
- }
- }
用法七:關(guān)于枚舉集合的使用java.util.EnumSet和java.util.EnumMap是兩個枚舉集合。EnumSet保證集合中的元素不重復(fù);EnumMap中的 key是enum類型,而value則可以是任意類型。關(guān)于這個兩個集合的使用就不在這里贅述,可以參考JDK文檔。 關(guān)于枚舉的實現(xiàn)細(xì)節(jié)和原理請參考: 參考資料:《ThinkingInJava》第四版 http://softbeta./blog/1185573
我的這篇文章,因為是轉(zhuǎn)載的,可能基本就沒有變動,導(dǎo)致被某人踩了一腳。覺得不符合我大師兄的性格。下面我把自己的使用理解給整理一下。 也是因為因為當(dāng)時剛剛開始學(xué)習(xí)吧。把平時自以為了解的東西都只是大概了解了一下,說到底,還是自以為了解了,其實轉(zhuǎn)眼就不知道什么是什么了。 出來學(xué)習(xí),不習(xí)慣看代碼怎么能行呢? 下面是我自己的測試代碼。
- package com.lxk.enumTest;
-
- /**
- * Java枚舉用法測試
- * <p>
- * Created by lxk on 2016/12/15
- */
- public class EnumTest {
- public static void main(String[] args) {
- forEnum();
- useEnumInJava();
- }
-
- /**
- * 循環(huán)枚舉,輸出ordinal屬性;若枚舉有內(nèi)部屬性,則也輸出。(說的就是我定義的TYPE類型的枚舉的typeName屬性)
- */
- private static void forEnum() {
- for (SimpleEnum simpleEnum : SimpleEnum.values()) {
- System.out.println(simpleEnum + " ordinal " + simpleEnum.ordinal());
- }
- System.out.println("------------------");
- for (TYPE type : TYPE.values()) {
- System.out.println("type = " + type + " type.name = " + type.name() + " typeName = " + type.getTypeName() + " ordinal = " + type.ordinal());
- }
- }
-
- /**
- * 在Java代碼使用枚舉
- */
- private static void useEnumInJava() {
- String typeName = "f5";
- TYPE type = TYPE.fromTypeName(typeName);
- if (TYPE.BALANCE.equals(type)) {
- System.out.println("根據(jù)字符串獲得的枚舉類型實例跟枚舉常量一致");
- } else {
- System.out.println("大師兄代碼錯誤");
- }
-
- }
-
- /**
- * 季節(jié)枚舉(不帶參數(shù)的枚舉常量)這個是最簡單的枚舉使用實例
- * Ordinal 屬性,對應(yīng)的就是排列順序,從0開始。
- */
- private enum SimpleEnum {
- SPRING,
- SUMMER,
- AUTUMN,
- WINTER
- }
-
-
- /**
- * 常用類型(帶參數(shù)的枚舉常量,這個只是在書上不常見,實際使用還是很多的,看懂這個,使用就不是問題啦。)
- */
- private enum TYPE {
- FIREWALL("firewall"),
- SECRET("secretMac"),
- BALANCE("f5");
-
- private String typeName;
-
- TYPE(String typeName) {
- this.typeName = typeName;
- }
-
- /**
- * 根據(jù)類型的名稱,返回類型的枚舉實例。
- *
- * @param typeName 類型名稱
- */
- public static TYPE fromTypeName(String typeName) {
- for (TYPE type : TYPE.values()) {
- if (type.getTypeName().equals(typeName)) {
- return type;
- }
- }
- return null;
- }
-
- public String getTypeName() {
- return this.typeName;
- }
- }
- }
然后是測試的結(jié)果圖:
簡單的例子,大家基本都用過,看不懂的基本都是第二個例子。可以看到,在第二個例子里面,后面帶有參數(shù),其實可以這么理解。 enum這個關(guān)鍵字,可以理解為跟class差不多,這也個單獨的類。可以看到,上面的例子里面有屬性,有構(gòu)造方法,有g(shù)etter,也可以有setter,但是一般都是構(gòu)造傳參數(shù)。還有其他自定義方法。那么在這些東西前面的,以逗號隔開的,最后以分號結(jié)尾的,這部分叫做,這個枚舉的實例。也可以理解為,class new 出來的實例對象。這下就好理解了。只是,class,new對象,可以自己隨便new,想幾個就幾個,而這個enum關(guān)鍵字,他就不行,他的實例對象,只能在這個enum里面體現(xiàn)。也就是說,他對應(yīng)的實例是有限的。這也就是枚舉的好處了,限制了某些東西的范圍,舉個栗子:一年四季,只能有春夏秋冬,你要是字符串表示的話,那就海了去了,但是,要用枚舉類型的話,你在enum的大括號里面把所有的選項,全列出來,那么這個季節(jié)的屬性,對應(yīng)的值,只能在里面挑。不能有其他的。 我上面的例子,就是根據(jù)typeName,你可以從那些例子里面挑選到唯一的一個TYPE類型的枚舉實例--TYPE.BALANCE。注意方法 TYPE type = TYPE.fromTypeName(typeName); 這個方法的返回類型就是這個TYPE枚舉類型的。 這下就好理解,這個枚舉是怎么在工作了吧
再補充一下: 上面那個帶參數(shù)的枚舉類型的實例里面實際上是三個屬性,除了我自定義的typeName以外,還有2個是系統(tǒng)自帶的??聪旅嬖创a的圖: 
看到這里之后,不知道你能不能理解下面圖片內(nèi)說明的話:下面圖片主要說明在使用枚舉時,的規(guī)范和標(biāo)準(zhǔn)。希望可以在實際開發(fā)時候用到 

最后補充一點: 也許你知道呢,但是也許你不知道呢?我是真的不知道,測了之后才知道?。?! 枚舉類型對象之間的值比較,是可以使用==,直接來比較值,是否相等的,不是必須使用equals方法的喲。 具體,請參考下面的鏈接: java 枚舉類比較是用==還是equals?
2017.11.07 更新 有的老鐵,說這個switch case怎么寫,我就在下面再啰嗦一下。 - private static void testSwitchCase() {
- String typeName = "f5";
- //這幾行注釋呢,你可以試著三選一,測試一下效果。
- //String typeName = "firewall";
- //String typeName = "secretMac";
- TypeEnum typeEnum = TypeEnum.fromTypeName(typeName);
- if (typeEnum == null) {
- return;
- }
- switch (typeEnum) {
- case FIREWALL:
- System.out.println("枚舉名稱(即默認(rèn)自帶的屬性 name 的值)是:" + typeEnum.name());
- System.out.println("排序值(默認(rèn)自帶的屬性 ordinal 的值)是:" + typeEnum.ordinal());
- System.out.println("枚舉的自定義屬性 typeName 的值是:" + typeEnum.getTypeName());
- break;
- case SECRET:
- System.out.println("枚舉名稱(即默認(rèn)自帶的屬性 name 的值)是:" + typeEnum.name());
- System.out.println("排序值(默認(rèn)自帶的屬性 ordinal 的值)是:" + typeEnum.ordinal());
- System.out.println("枚舉的自定義屬性 typeName 的值是:" + typeEnum.getTypeName());
- break;
- case BALANCE:
- System.out.println("枚舉名稱(即默認(rèn)自帶的屬性 name 的值)是:" + typeEnum.name());
- System.out.println("排序值(默認(rèn)自帶的屬性 ordinal 的值)是:" + typeEnum.ordinal());
- System.out.println("枚舉的自定義屬性 typeName 的值是:" + typeEnum.getTypeName());
- break;
- default:
- System.out.println("default");
- }
- }
然后,就是運行結(jié)果的截圖。
老鐵們,看完這個枚舉,你要懂個概念,那就是,這個枚舉,他是個對象,就像你定義的Student類,Person類,等等一些個類一樣。 要有這么個概念。只要是個類,他就可以有構(gòu)造函數(shù),可以有屬性,可以有方法。 對的,老鐵,你對這個屬性,構(gòu)造函數(shù)啥的,有概念吧,沒有的話,我可就郁悶啦。 然后,你就看到,這個地方有2個默認(rèn)的屬性,一個是name,一個是ordinal,這2個屬性就像你定義Student類和Person類的name和age一樣, 只不過,這2個是系統(tǒng)自帶的屬性,不用你自己去定義啦。 你也可以給這個枚舉類,也就是你自己聲明的枚舉,隨便加屬性。 我上面代碼例子里面的那個TypeEnum那個枚舉,就是這么干的,就簡單的添加了個自定義屬性typeName, 雖然他有自己的name了,那姑且叫我這個自定義的屬性叫別名吧。 可以看到,我例子里面就是通過自己寫的那個構(gòu)造方法給我這個自定義的屬性初始化值的。 還有,這個構(gòu)造方法是不可以,也不被運行public的,不信,你可以試試。 還有,你不能對系統(tǒng)自帶的name屬性,在構(gòu)造函數(shù)里面賦值,沒有為什么。
|