1. 程式人生 > >Java瘋狂講義筆記——列舉類

Java瘋狂講義筆記——列舉類

列舉類 ——Java5
【基礎知識】
1,定義列舉類——關鍵字 enum (地位與class、interface相同)。
2,列舉類是一個特殊的類,可以有成員變數、方法,實現一個或多個介面,定義自己的構造器。
3,一個Java原始檔中最多隻能定義一個public訪問許可權的列舉類,且該Java原始檔也必須和該列舉類的類名相同。

【列舉類與普通類的區別】
1,使用enum定義的列舉類預設繼承了java.lang.Enum類,不是預設繼承Object類。因此列舉類不能顯式繼承其它父類。
其中,java.lang.Enum類實現類java.lang.Serializable和java.lang.Comparable兩個介面。
2,使用enum定義、非抽象的列舉類預設會使用final修飾,因此列舉類不能派生子類。
3,列舉類的構造器只能使用private訪問控制符,省略系統自動新增。
4,列舉類的所有例項必須在列舉類第一行顯式列出,否則這個列舉類永遠都不能產生例項。
列出這些例項時,系統自動新增public static final修飾。
5,呼叫列舉類例項:
類名.例項名
如:SeasonEnum.SPRING
6,產生例項可以用valueOf方法,如:Gender g = Enum.valueOf(Gender.class, "FEMALE");
列舉類的例項只能是列舉值,不是隨意通過new來建立物件。

例子——定義列舉類:
public enum SeasonEnum
{
  //在第一行列出4個列舉例項
  SPRING, SUMMER, FALL, WINTER;
}

 

【方法】
* 預設提供了values()方法,返回列舉類所有例項。 如:
  //列印SeasonEnum的所有例項
  for(SeasonEnum s : SeasonEnum.values())
  {
    System.out.println(s); //實際呼叫了toString方法
  }

* public final int compareTo(E o):與指定列舉物件比較順序,同一個列舉例項只能與相同型別的列舉例項進行比較。
如果該列舉物件位於指定列舉物件之後,返回正整數;之前,返回負整數;否則,返回0。

* public final String name():返回此列舉例項的名稱,這個名稱就是定義列舉類時列出的所有列舉值之一。
應優先考慮toString方法,因為toString返回更友好的名稱。

* public final int ordinal():返回列舉值在列舉類中的索引值(列舉值在列舉宣告中的位置,第一個列舉值的索引值為0)。

* public String toString():返回列舉常量名稱,與預設與name()方法相似,只是該方法可以被重寫。

* public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name):
靜態方法,返回指定列舉類中指定名稱的列舉值。 名稱必須與在列舉類中宣告列舉值時所用的識別符號完全匹配,不允許使用額外的空白字元。

 


【例項——列舉類的應用及改進】
enum Gender
{
  MALE, FEMALE;
  private String name;
  public void setName(String name) {
    switch (this) {
      case MALE:
        if(name.equals("男")) {
          this.name = name;
        } else {
          System.out.println("引數錯誤");
          return;
        }
        break;
      case FEMALE:
        if (name.equals("女")) {
          this.name = name;
        } else {
          System.out.println("引數錯誤");
          return;
        }
        break;
    }
  }
  public String getName() {
    return this.name;
  }
}


public class Demo
{
  public static void main(String[] args) {
    Gender g = Enum.valueOf(Gender.class, "FEMALE");
    g.setName("女");
    System.out.println(g + "代表" + g.getName());
    //設定name值錯誤會出現引數錯誤提示
    g.setName("男");
    System.out.println(g + "代表" + g.getName());
  }
}

//以上的做法並不太好,因為列舉類應該設定為一個不可變類,它的成員變數不應該允許改變。
//建議將列舉成員變數都用private final修飾。
//因為成員變數都被私有化,因此必須在構造器中為這些成員變數指定初始值(或在定義成員變數時指定預設值,或在初始化塊中指定初始值)。

enum Gender_improve
{
  MALE("男"), FEMALE("女");
  //先當於:
  //public static final Gender MALE = new Gender("男");
  //public static final Gender FEMALE = new Gender("女");
  private final String name;
  private Gender_improve(String name) {
  this.name = name;
  }
  public String getName() {
    return this.name;
  }
}

【實現介面的列舉類】
1,列舉類實現介面的方法與普通類完全一樣。
2,如果由列舉類實現接口裡的方法,則每個列舉值在呼叫該方法時都會有相同的行為方式(因為方法體完全一樣)。
3,如果需要每個列舉值在呼叫該方法時呈現出不同的行為,則可以讓每個列舉值分別實現該方法。

例子:
interface GenderDesc
{
  void info();
}

enum Gender implements GenderDesc
{
  MALE("男") {
    public void info() {
      System.out.println("這個列舉值代表男性");
    }
  }, //注意逗號
  FEMALE("女") {
    public void info() {
      System.out.println("這個列舉值代表女性");
    }
  }; //注意分號
  private final String name;
  private Gender(String name) {
    this.name = name;

  }
  public String getName() {
    return this.name;
  }
}

4,當建立MALE和FEMALE列舉值時,不是直接建立Gender列舉類的例項,而實現當與建立Gender的匿名內部子類的例項。
5,編譯以上檔案,發現生成了Gender.class、Gender$1.class、Gender$2.class三個檔案。
這驗證了4結論,MALE和FEMALE實際上是Gender匿名內部子類的例項。


【抽象列舉類——有子類的抽象類】
1,並不是所有的列舉類都使用了final修飾,非抽象的列舉類才預設使用final修飾。
2,只要列舉類包含了抽象方法,它就是抽象列舉類,系統預設用abstract修飾,而不是final。
注意,不能用abstract關鍵字定義抽象列舉類,因為系統會自動新增。
3,因為列舉類需要顯式建立列舉值,而不是作為父類,所以定義每個列舉值時必須為抽象方法提供實現,否則會編譯錯誤。