第19章 列舉型別
阿新 • • 發佈:2018-12-01
列舉型別
public enum Spiciness {
/**
* 具名值,列舉型別的例項,常量
* 按照常量書寫的慣例它們都用大寫字母表示
*/
NOT, MID, MEDIUM, HOT, FLAMING
}
import org.testng.annotations.Test; public class SpicinessTest { /** * 在你建立enum時,編譯器會自動新增一些有用的特性 * */ @Test(enabled = false) public void testSimpleEnumUse() { Spiciness howHot = Spiciness.MEDIUM; // 輸出MEDIUM。 編譯器自動新增toString方法,顯示enum例項的名字 System.out.print(howHot); } /** * 儘管enum看起來像是一種新的資料型別,但是這個關鍵字知識為enum生成對應的類時,產生某些編譯行為 */ @Test(enabled = true) public void testEnumOrder() { // static values()方法,是由編譯器新增的static方法,Enum類中並沒有values方法,按照enum常量的宣告順序,產生這些常量值構成的陣列 for(Spiciness s : Spiciness.values()) { // ordinal()方法,用來表示某個特定enum常量的宣告順序 System.out.println(s + ", ordinal " + s.ordinal()); } } }
基本enum特性
public enum Shrubbery {
/**
* 建立enum時,編譯器會為你生成一個相關的類,這個類繼承自java.lang.Enum
*/
GROUND, CRAWLING, HANGING
}
import org.testng.annotations.Test; public class ShrubberyTest { @Test(enabled = true) public void testShrubbery() { for(Shrubbery s : Shrubbery.values()) { // ordinal()方法返回一個int值,這是每個enum例項在宣告時的次序,從0開始 System.out.println(s + " ordinal: " + s.ordinal()); System.out.println(s.compareTo(Shrubbery.CRAWLING) + " "); System.out.println(s.equals(Shrubbery.CRAWLING) + " "); System.out.println(s == Shrubbery.CRAWLING); // 在enum例項上呼叫getDeclaringClass()方法,我們就能知道其所屬的enum類 System.out.println(s.getDeclaringClass()); // name()方法返回enum例項宣告時的名字,這與使用toString()方法效果相同 System.out.println(s.name()); System.out.println("----------------------"); } for(String s : "HANGING CRAWLING GROUND".split(" ")) { /** * valueOf()方法根據給定的名字返回相應的enum例項,如果不存在給定名字的例項,將會丟擲異常 * s == null, throw new NullPointerException * s not exist throw new IllegalArgumentException */ Shrubbery shrubbery = Enum.valueOf(Shrubbery.class, s); System.out.println(shrubbery); } } }
向enum中新增新方法
public enum OzWitch { /** 如果你打算定義自己的方法,那麼必須在enum例項序列的最後新增一個分號 * Java要求你必須先定義enum例項,如果在定義enum例項之前定義了任何方法或屬性,那麼編譯時就會得到錯誤資訊 */ WEST("Miss Gulch, aka the Wicked Witch of the West"), NORTH("Glinda, the Good Witch of the North"), EAST("Wicked Witch of the East, wearer of the Ruby " + "Slippers, crushed by Dorothy's house"), SOUTH("Good by inference, but missing"); private String description; OzWitch(String description) { this.description = description; } public String getDescription() { return description; } }
import org.testng.annotations.Test;
public class OzWitchTest {
@Test
public void test() {
for(OzWitch witch : OzWitch.values()) {
System.out.println(witch + ": " + witch.getDescription());
}
}
}
覆蓋enum中的方法
public enum SpaceShip {
SCOUT, CARGO, TRANSPORT, CRUISER, BATTLESHIP, MOTHERSHIP;
/**
* 覆蓋enum的toString()方法
* @return
*/
public String toString() {
String id = name();
String lower = id.substring(1).toLowerCase();
return id.charAt(0) + lower;
}
}
import org.testng.annotations.Test;
public class SpaceShipTest {
@Test
public void test() {
for(SpaceShip s : SpaceShip.values()) {
System.out.println(s);
}
}
}
switch
public class Burrito {
Spiciness degree;
public Burrito(Spiciness degree) {
this.degree = degree;
}
/**
* enum有一個特別實用的特性,即它可以在switch語句內使用
*/
public void describe() {
System.out.print("This burrito is ");
switch (degree) {
case NOT:
System.out.println("not spicy at all.");
break;
case MID:
case MEDIUM:
System.out.println("a little hot.");
break;
case HOT:
case FLAMING:
default:
System.out.println("maybe too hot.");
}
}
}
import org.testng.annotations.Test;
public class BurritoTest {
@Test(enabled = true)
public void testDescribe() {
Burrito
plain = new Burrito(Spiciness.NOT),
greenChile = new Burrito(Spiciness.MEDIUM),
jalapeno = new Burrito(Spiciness.HOT);
plain.describe();
greenChile.describe();
jalapeno.describe();
}
}
EnumSet
public enum AlarmPoints {
STAIR1, STAIR2, LOBBY, OFFICE1, OFFICE2, OFFICE3,
OFFICE4, BATHROOM, UTILITY, KITCHEN
}
import org.testng.annotations.Test;
import java.util.EnumSet;
/**
* 使用static import 簡化enum常量的使用
*/
import static com.dmw.enumerated.AlarmPoints.*;
public class EnumSetTest {
@Test
public void test() {
// Empty set,EnumSet中的元素必須來自一個enum
EnumSet<AlarmPoints> points = EnumSet.noneOf(AlarmPoints.class);
points.add(BATHROOM);
System.out.println(points);
points.addAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
System.out.println(points);
points = EnumSet.allOf(AlarmPoints.class);
System.out.println(points);
points.removeAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
System.out.println(points);
points.removeAll(EnumSet.range(OFFICE1, OFFICE4));
System.out.println(points);
points = EnumSet.complementOf(points);
System.out.println(points);
}
}
EnumMaps
import java.util.EnumMap;
import java.util.Map;
import static com.dmw.enumerated.AlarmPoints.*;
public class EnumMaps {
public static void main(String[] args) {
EnumMap<AlarmPoints, Command> em = new EnumMap<>(AlarmPoints.class);
em.put(KITCHEN, new Command() {
@Override
public void action() {
System.out.println("Kitchen fire");
}
});
em.put(BATHROOM, new Command() {
@Override
public void action() {
System.out.println("Bathroom alert!");
}
});
for(Map.Entry<AlarmPoints, Command> e : em.entrySet()) {
System.out.println(e.getKey() + ":");
e.getValue().action();
}
try {
em.get(UTILITY).action();
} catch (Exception e) {
System.out.println(e);
}
}
}
interface Command {
void action();
}
常量相關方法
import java.text.DateFormat;
import java.util.Date;
/**
* 1. Java的enum有一個非常有趣的特性,即它允許程式設計師為enum例項編寫方法,從而為每個enum例項賦予各自不同的行為
* 2. 通過相應的enum例項,我們可以呼叫對應的方法。這通常也稱為表驅動的程式碼(table-driven code, 和命令模式有一定的相似之處)
* 3. 每個enum元素(例如DATE_TIME)都是一個ConstantSpecificMethod的static final例項
*/
public enum ConstantSpecificMethod {
DATE_TIME {
@Override
String getInfo() {
return DateFormat.getDateInstance().format(new Date());
}
},
CLASSPATH {
@Override
String getInfo() {
return System.getenv("CLASSPATH");
}
},
VERSION {
@Override
String getInfo() {
return System.getProperty("java.version");
}
};
abstract String getInfo();
}
import org.testng.annotations.Test;
public class ConstantSpecificMethodTest {
@Test
public void test() {
for(ConstantSpecificMethod csm : ConstantSpecificMethod.values()) {
System.out.println(csm.getInfo());
}
}
}
比匿名內部類更加簡潔高效
import java.util.EnumSet;
/**
* 與使用匿名內部類相比較,定義常量相關方法的語法更高效、簡潔
*/
public class CarWash {
public enum Cycle {
UNDERBODY {
@Override
void action() {
System.out.println("Spraying the underbody");
}
},
WHEELWASH {
@Override
void action() {
System.out.println("Washing the wheels");
}
},
PREWASH {
@Override
void action() {
System.out.println("Loosening the dirt");
}
},
BASIC {
@Override
void action() {
System.out.println("The basic wash");
}
},
HOTWAX {
@Override
void action() {
System.out.println("Applying hot wax");
}
},
RINSE {
@Override
void action() {
System.out.println("Rinsing");
}
},
BLOWDRY {
@Override
void action() {
System.out.println("Blowing dry");
}
};
abstract void action();
}
EnumSet<Cycle> cycles = EnumSet.of(Cycle.BASIC, Cycle.RINSE);
public void add(Cycle cycle) {
cycles.add(cycle);
}
public void washCar() {
for(Cycle c : cycles) {
c.action();
}
}
@Override
public String toString() {
return cycles.toString();
}
public static void main(String[] args) {
CarWash wash = new CarWash();
System.out.println(wash);
wash.washCar();
// Order of addition is unimportant
wash.add(Cycle.BLOWDRY);
// Duplicates ignored
wash.add(Cycle.BLOWDRY);
wash.add(Cycle.RINSE);
wash.add(Cycle.HOTWAX);
System.out.println(wash);
wash.washCar();
}
}