Java枚舉類型enum


枚舉的語法
1.Enum的全稱為enumeration,中文俗稱枚舉類,學過C/C++等語言的人,應該都對它略知一二。
    但在Java語言規范中,是在JDK 5版本中才引入的,存放在 java.lang 包中。在Java版的Enum實質是語法糖,其聲明方式如下:

【代碼1】

package com.enumtest;
public enum Color
{
RED,BLUE,BLACK,YELLOW,GREEN //注意這里可以沒有分號
}
  enum是用來聲明枚舉的關鍵字,聲明定義的類都隱含繼承了一個父類(java.lang.Enum<E>),因此枚舉不能再繼承,但仍可實現接口。
    該父類有兩個私有屬性name(枚舉類型的名稱)和ordinal(枚舉實例被創建的序數),分別通過name()和ordinal()暴露出來了.
    定義在枚舉類型里的每一個枚舉實例都將映射到Enum的子類中,其實例的名稱和在枚舉類型里定義的順序都會傳入到這個構造函數里 : protected Enum(String name, int ordinal)。
2.如果想更清楚了解一下Enum,可以用反編譯工具把自己定義的枚舉反編譯一下就一目了然了,它就是一個普通的類,只是Java語言規范從Code角度進行了限制,執行javap com.enumtest.Color命令如下:
【代碼2】
package com.enumtest;
public final class Color extends java.lang.Enum{
public static final Color RED;
public static final Color BLUE;
public static final Color BLACK;
public static final Color YELLOW;
public static final Color GREEN;
static {};
public static Color[] values();
public static Color valueOf(java.lang.String);
}
3.所有枚舉類都繼承了Enum的方法,下面我們詳細介紹這些方法。
(1) ordinal()方法: 返回枚舉值在枚舉類種的順序。這個順序根據枚舉值聲明的順序而定。
    Color.RED.ordinal(); //返回結果:0
    Color.BLUE.ordinal(); //返回結果:1
(2) compareTo()方法: Enum實現了java.lang.Comparable接口,因此可以比較象與指定對象的順序。Enum中的compareTo返回的是兩個枚舉值的順序之差。當然,前提是兩個枚舉值必須屬於同一個枚舉類,否則會拋出ClassCastException()異常。(具體可見源代碼)
    Color.RED.compareTo(Color.BLUE); //返回結果 -1
(3) values()方法: 靜態方法,返回一個包含全部枚舉值的數組。
    Color[] colors=Color.values();
    for(Color c:colors){
        System.out.print(c+",");
    }//返回結果:RED,BLUE,BLACK YELLOW,GREEN,
(4) toString()方法: 返回枚舉常量的名稱。
    Color c=Color.RED;
    System.out.println(c);//返回結果: RED
(5) valueOf()方法: 這個方法和toString方法是相對應的,返回帶指定名稱的指定枚舉類型的枚舉常量。
    Color.valueOf("BLUE"); //返回結果: Color.BLUE
(6) equals()方法: 比較兩個枚舉類對象的引用。
4. 如果定義的枚舉有自己的構造函數必須聲明私有的。

5. 注意以下區別:
【代碼3】

enum Color3{}

enum Color4
{
RED
}

enum Color5
{
RED;
}

enum Color6
{
RED;
public void test(){}
}

enum Color7
{
public void test(){}
// RED; //錯誤!!!!
}

enum Color8
{
;
public void test(){}
}
在enum Color3中是一個空的枚舉;在enum Color4和Color5中有一個RED的枚舉值,后面可以加分號或者不加分號;如果在枚舉值后面添加方法,那么在枚舉值的最后添加一個分號,如enum Color6;如果像enum Color7一樣想把枚舉值定義在方法后面是非法的,編譯器會提示錯誤;當然也可以像enum Color8一樣定義,注意方法test()之前的分號。

枚舉的用法
(1) 常用於對同一類常量進行分類。見代碼1.
(2) 聲明接口方法時,輸入參數類型采用枚舉比用原始類型值常量更嚴謹.
(3) 常量有時往往不僅僅只是一個值,有可能會包含多個屬性,此時很適合用枚舉
(4) 有時常量對象需要從配置文件中讀取其描述信息或者UI顯示信息,此時也適合用枚舉
(5) 從Java語法層面來說,枚舉可以在switch使用,在if中可直接進行比較 。
【代碼4】

package com.enumtest;

public enum Color
{
RED,BLUE,BLACK,YELLOW,GREEN; //注意這里有分號

public static void valuePrint(Color color)
{
switch(color)
{
case RED:
System.out.println(RED);
break;
case BLUE:
System.out.println(BLUE);
break;
case BLACK:
System.out.println(BLACK);
break;
case YELLOW:
System.out.println(YELLOW);
break;
case GREEN:
System.out.println(GREEN);
break;
default:
break;
}
}

public static void main(String args[])
{
Color color = Color.RED;
valuePrint(color);
EnumTest.valuePrint(color);
}
}

class EnumTest
{
public static void valuePrint(Color color)
{
switch(color)
{
case RED:
System.out.println(Color.RED);//注意這里的Color.RED不能寫成RED,而case中的必須寫成RED。
break;
case BLUE:
System.out.println(Color.BLUE);
break;
case BLACK:
System.out.println(Color.BLACK);
break;
case YELLOW:
System.out.println(Color.YELLOW);
break;
case GREEN:
System.out.println(Color.GREEN);
break;
default:
break;
}
}
}
運行結果:
RED
RED
(6) 聲明枚舉屬性時最好用public final修飾,使用起來會非常方便
(7) 自定義枚舉時,建議不要使用自帶的name()和ordinal()方法返回值來與原始值類型轉換,這樣業務不依賴其枚舉的名字和順序
【代碼5】
package com.enumtest;

public enum Color2
{
RED("紅色",1),BLUE("藍色",2),BLACK("黑色",3),YELLOW("黃色",4),GREEN("綠色",5);

public final String name;
public final int index;

private Color2(String name, int index)
{
this.name = name;
this.index = index;
}

public static String getName(int index)
{
for(Color2 c: Color2.values())
{
if(c.getIndex() == index)
{
return c.name;
}
}
return null;
}

public static void main(String[] args)
{
System.out.println(getName(1));
}

public String getName()
{
return name;
}

public int getIndex()
{
return index;
}
}
運行結果:紅色
(8) 重載枚舉的方法toString
【代碼6】

package com.enumtest;

public enum Color2
{
RED("紅色",1),BLUE("藍色",2),BLACK("黑色",3),YELLOW("黃色",4),GREEN("綠色",5);

public final String name;
public final int index;

private Color2(String name, int index)
{
this.name = name;
this.index = index;
}

public static String getName(int index)
{
for(Color2 c: Color2.values())
{
if(c.getIndex() == index)
{
return c.toString();
}
}
return null;
}

public static void main(String[] args)
{
System.out.println(getName(1));
}

@Override
public String toString()
{
return this.index+"_"+this.name;
}

public String getName()
{
return name;
}

public int getIndex()
{
return index;
}
}
(9)實現接口。所有的枚舉都繼承自java.lang.Enum類。由於java不支持多繼承,所以枚舉對象不能再繼承其他的類。
【代碼7】
package com.enumtest;

public interface Behaviour
{
void print();
String getInfo();
}
【代碼8】
package com.enumtest;

public enum Color9 implements Behaviour
{
RED("紅色",1),BLUE("藍色",2),BLACK("黑色",3),YELLOW("黃色",4),GREEN("綠色",5);

public final String name;
public final int index;

private Color9(String name, int index)
{
this.name = name;
this.index = index;
}

@Override
public void print()
{
System.out.println(this.index+":"+this.name);
}

@Override
public String getInfo()
{
return this.name;
}
}
(10) 可以創建一個enum類,把它看做一個普通的類。除了它不能繼承其他類。(Java是單繼承,它已經繼承了Enum),可以添加其他的方法,覆蓋它本身的方法。
(11) values()方法是編譯器插入到enum定義中的static方法,所以,當你將enum實例向上轉型為父類Enum是,values()就不可訪問了。解決辦法:在Class中有一個getEnumConstants()方法,所以即便Enum接口中沒有values()方法,我們仍然可以通過Class對象取得所有的enum實例。
【代碼9】
package com.enumtest;

public enum Color
{
RED,BLUE,BLACK,YELLOW,GREEN; //注意這里有分號

public void print()
{
for(Color c : Color.class.getEnumConstants())
{
System.out.println(c.toString());
}
}

public static void main(String args[])
{
Color.RED.print();
}
}
(12) 無法從enum繼承子類,如果需要擴展enum中的元素,在一個接口的內部,創建實現該接口的枚舉,以此將元素進行分組。達到將枚舉元素進行分組。
【代碼10】
package com.enumtest;

public interface Food
{
enum Coffee implements Food
{
BLACK_COFFEE, DECAF_COFFEE,LATTE;
}

enum Dessert implements Food
{
FRUIT,CAKE,GELATO;
}
}
(13) java.util.EnumSet和java.util.EnumMap是兩個枚舉集合。EnumSet保證集合中的元素不重復;EnumMap中的 key是enum類型,而value則可以是任意類型。
【代碼11】
package com.enumtest;

import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Set;

public class LightTest
{
public enum Light{
RED(1),GREEN(2),YELLOW(3);

public final int nCode;

private Light(int nCode)
{
this.nCode = nCode;
}
}

public static void testTraversalEnum()
{
Light[] allLight = Light.values();
for(Light aLight:allLight)
{
System.out.println(aLight.name()+" "+aLight.ordinal()+" "+aLight);
}
}

public static void testEnumMap()
{
EnumMap<Light,String> currEnumMap = new EnumMap<Light,String>(Light.class);
currEnumMap.put(Light.RED, "紅色");
currEnumMap.put(Light.GREEN, "綠色");
currEnumMap.put(Light.YELLOW, "黃色");
Set<Light> set = currEnumMap.keySet();
for(Light aLight:set)
{
System.out.println(aLight.name()+" "+aLight.ordinal()+" "+aLight);
}
}

public static void testEnumSet()
{
EnumSet<Light> currEnumSet = EnumSet.allOf(Light.class);
for(Light aLightSetElement : currEnumSet)
{
System.out.println(aLightSetElement);
}
}

public static void main(String[] args)
{
testTraversalEnum();
testEnumMap();
testEnumSet();
}
}
運行結果:(略)
(14) 使用enum的職責鏈(Chain of Responsibility) .這個關系到設計模式的職責鏈模式。以多種不同的方法來解決一個問題。然后將他們鏈接在一起。當一個請求到來時,遍歷這個鏈,直到鏈中的某個解決方案能夠處理該請求。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com