獻給我老公 - Java列舉型別
列舉型別是一種特殊的資料型別。具有列舉型別的變數,其取值範圍會被限定在預定義的常量池中。該變數的值必須為預定義取值的其中之一。常見的例子有指南針的方向(東,西,南,北)和星期幾。
由於是常量,列舉型別中定義的欄位均為大寫字母。
在Java程式語言中,通過關鍵字 enum 來定義一個列舉型別。例如,定義一個一週有幾天的列舉型別:
public enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }
在任何需要定義一個限定常量池的場景下,你就需要用到列舉型別。這包括自然界的列舉型別,例如銀河系的星球,編譯時就知道所有取值情況的資料集合——例如,一個選單的選項,命令列標記等等。
這裡給出一個以上定義的Day列舉型別應用例項:
public class EnumTest { Day day; public EnumTest(Day day) { this.day = day; } public void tellTheTruth() { switch (day) { case MONDAY: System.out.println("Mondays are bad if my husband is not around."); break; case FRIDAY: System.out.println("Fridays are better if my husband could have dinner with me."); break; case SATURDAY: case SUNDAY: System.out.println("Weekends are best if my husband is by my side."); break; default: System.out.println("Midweek days are good if my husband is able to have lunch with me."); break; } } public static void main(String[] args) { EnumTest firstDay = new EnumTest(Day.MONDAY); firstDay.tellTheTruth(); EnumTest thirdDay = new EnumTest(Day.WEDNESDAY); thirdDay.tellTheTruth(); EnumTest fifthDay = new EnumTest(Day.FRIDAY); fifthDay.tellTheTruth(); EnumTest sixthDay = new EnumTest(Day.SATURDAY); sixthDay.tellTheTruth(); EnumTest seventhDay = new EnumTest(Day.SUNDAY); seventhDay.tellTheTruth(); } }
輸出為:
Mondays are bad if my husband is not around.
Midweek days are good if my husband is able to have lunch with me.
Fridays are better if my husband could have dinner with me.
Weekends are best if my husband is by my side.
Weekends are best if my husband is by my side.
Java程式語言中的列舉型別比其他語言中的同種型別更為強大。enum在宣告時定義了一個類(稱為一個列舉型別)。列舉類可以包含方法以及其他屬性。在建立一個列舉時編譯器會自動新增一些特殊方法。例如,它們都有一個靜態的 values 方法,這個方法會按定義時的順序返回列舉中的所有值。這個方法常與 for-each 連用以遍歷一個列舉型別中的所有值。例如,下面這段選自 Planet 類的程式碼遍歷了太陽系的所有星球。
for (Planet p : Planet.values()) { System.out.printf("Your weight on %s is %f%n", p, p.surfaceWeight(mass)); }
注意: 所有列舉隱式繼承
java.lang.Enum
. 由於一個類只能有一個父類,Java語言不支援多繼承,所以列舉不能繼承其他類。
在接下來的例子中,Planet 是一個表示太陽系中所有星球的列舉型別。它們在定義時加入了體積和半徑常量作為其屬性。
每個列舉常量在宣告時都有體積和半徑作引數。在常量建立時這些值將被傳入構造方法。Java要求先定義常量,優先於其他欄位或者方法。並且當有其他欄位和方法存在時,列舉常量列表必須以分號結尾。
注意: 列舉型別的構造方法必須定義為包私有或私有訪問級別。它會自動建立定義在類體前部的常量。構造方法不能被手動呼叫。
除了屬性和構造方法,Planet還提供了獲取星球上表面重力和物體質量的方法。這裡給出一個樣例程式,以地球上的質量(任意單位)為入參,計算其在其他星球上的質量(相同單位):
public enum Planet { MERCURY (3.303e+23, 2.4397e6), VENUS (4.869e+24, 6.0518e6), EARTH (5.976e+24, 6.37814e6), MARS (6.421e+23, 3.3972e6), JUPITER (1.9e+27, 7.1492e7), SATURN (5.688e+26, 6.0268e7), URANUS (8.686e+25, 2.5559e7), NEPTUNE (1.024e+26, 2.4746e7); private final double mass; // in kilograms private final double radius; // in meters Planet(double mass, double radius) { this.mass = mass; this.radius = radius; } private double mass() { return mass; } private double radius() { return radius; } // universal gravitational constant (m3 kg-1 s-2) public static final double G = 6.67300E-11; double surfaceGravity() { return G * mass / (radius * radius); } double surfaceWeight(double otherMass) { return otherMass * surfaceGravity(); } public static void main(String[] args) { if (args.length != 1) { System.err.println("Usage: java Planet <earth_weight>"); System.exit(-1); } double earthWeight = Double.parseDouble(args[0]); double mass = earthWeight/EARTH.surfaceGravity(); for (Planet p : Planet.values()) System.out.printf("Your weight on %s is %f%n", p, p.surfaceWeight(mass)); } }
如果從命令列執行Planet.class並且輸入引數175,會得到以下輸出:
$ java Planet 175 Your weight on MERCURY is 66.107583 Your weight on VENUS is 158.374842 Your weight on EARTH is 175.000000 Your weight on MARS is 66.279007 Your weight on JUPITER is 442.847567 Your weight on SATURN is 186.552719 Your weight on URANUS is 158.397260 Your weight on NEPTUNE is 199.207413