enum基本使用
:
package com.enumTest;
enum Shrubbery {
GROUND, CRAWLING, HANGING}
public class EnumClass {
public static void main(String[] args) {
for (Shrubbery s : Shrubbery.values()) {
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);
System.out.println(“s.getDeclaringClass:” + s.getDeclaringClass()
+ “getClass:” + s.getClass());
System.out.println(s.name());
System.out.println(“——————————-“);
}
String[] arrayString=”HANGING CRAWLING GROUND”.split(” “);
for (String s : arrayString) {
Shrubbery shrub = Enum.valueOf(Shrubbery.class, s);
System.out.println(shrub);
}
}
}
- 每个enum实例(GROUND, CRAWLING, HANGING)都记录一个次序original(0,1,2).
2.实现了Comparable接口,重写了compareTo按照 original来比较次序,且仅运行同一个enum类型实例做比较.
3.equals 比较内存地址
4.实现了 Serializable接口.
除了少量限制,我们可以把enum当作普通类型对待:
package com.enumTest;
public enum OzWitch {
//you must define enum instances firstly.
WEST("west"), NORTH("north"), EAST("east"), SOUTH("south");
private String description;
//even if the constructor is public .. , it‘s nonsense!
private OzWitch(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public static void main(String[] args) {
for (OzWitch witch : OzWitch.values()) {
System.out.println(witch + ":" + witch.getDescription());
}
}
}
enum 类型可以用于switch 语句中
.switch(integer or enum){
case ….
}
enum Signal {
GREEN, YELLOW, RED
}
public class TrafficLight {
Signal color = Signal.RED;
public void change() {
switch (color/*枚举实例*/) {
//case ** 被强制用color类型的实例
case RED:
color = Signal.GREEN;
break;
case GREEN:
color = Signal.YELLOW;
break;
case YELLOW:
color = Signal.RED;
break;
}
}
public String toString() {
return "The traffic light is " + color;
}
public static void main(String[] args) {
TrafficLight t = new TrafficLight();
for (int i = 0; i < 7; i++) {
System.out.println(t);
t.change();
}
}
}
关键字 enum 与 java.lang.Enum 的区别:
我们看以下代码:
enum Explore { HERE, THERE }
public class Reflection {
public static Set analyze(Class
package com.enumTest;
//枚举中的枚举
public enum Course {
//定义三个枚举实例
APPETIZER(Food.Appetizer.class),
MAINCOURSE(Food.MainCourse.class),
COFFEE(Food.Coffee.class);
//定一个域 用来得到 每个实例中包含的实例
private Food[] allFood;
//构造器获得一个枚举类型中的所有实例
//这个构造器 ,通过入参获取该入参对应的所有实例
Course(Class<? extends Food> clazz) {
allFood = clazz.getEnumConstants();
}
//随机获取一个枚举(如 APPETIZER)中的枚举实例(如 SALAD,SOUP,RED_WINE)中的一个
public Food randomSelection() {
return Enums.random(allFood);
}
public static void main(String[] args) {
for (int i = 0; i < Course.values().length; i++) {
for (Course course : Course.values()) {
Food food = course.randomSelection();
System.out.println(food);
}
System.out.println(“———–”);
}
另外,还有一种简洁的组织方式(随便选择一种即可,个人倾向第一种,clear!):
public enum Meal2 {
APPETIZER(Food.Appetizer.class),
MAINCOURSE(Food.MainCourse.class),
DESSERT(Food.Dessert.class),
COFFEE(Food.Coffee.class);
private Food[] values;
private Meal2(Class<? extends Food> kind) {
736 Thinking in Java Bruce Eckel
values = kind.getEnumConstants();
}
public interface Food {
enum Appetizer implements Food {
SALAD, SOUP, SPRING_ROLLS;
}
enum MainCourse implements Food {
LASAGNE, BURRITO, PAD_THAI,
LENTILS, HUMMOUS, VINDALOO;
}
enum Dessert implements Food {
TIRAMISU, GELATO, BLACK_FOREST_CAKE,
FRUIT, CREME_CARAMEL;
}
enum Coffee implements Food {
BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,
LATTE, CAPPUCCINO, TEA, HERB_TEA;
}
}
public Food randomSelection() {
return Enums.random(values);
}
public static void main(String[] args) {
for(int i = 0; i < 5; i++) {
for(Meal2 meal : Meal2.values()) {
Food food = meal.randomSelection();
System.out.println(food);
}
System.out.println("---");
}
}
} /* Same output as Meal.java *///:~
EnumSet
1.其操作比HashSet快,基于long的存储
2.EnumSet 中的元素 必须是 enum类型,初始化后元素的顺序与enum实例定义顺序一致
import java.util.EnumSet;
public class EnumSets {
public static void main(String[] args) {
EnumSet<AlarmPoints> points = EnumSet.noneOf(AlarmPoints.class);
points.add(AlarmPoints.BATHROOM);
System.out.println(points);
points.addAll(EnumSet.of(AlarmPoints.STAIR1, AlarmPoints.STAIR2,
AlarmPoints.KITCHEN));
System.out.println(points);
points = EnumSet.allOf(AlarmPoints.class);
// points.removeAll(EnumSet.of(AlarmPoints.STAIR1,AlarmPoints.STAIR2,AlarmPoints.KITCHEN));
System.out.println(points);
// 参数 rangefrom,rangeTo 都包含
points.removeAll(EnumSet.range(AlarmPoints.STAIR1, AlarmPoints.STAIR2));
System.out.println(points);
//求一个差集
points = EnumSet.complementOf(points);
System.out.println(points);
}
}
EnumSet基于long(64bit)构造, 通过EnumSet result = noneOf(elementType);初始化,EnumSet中的元素用一个bit来表示其存在。所以,如果初始化的enum元素个数超过64个则会增加long个数,如果小于64个,则会只有一个long的内存空间。
(如源码: elements 用来存元素)
/**
* Bit vector representation of this set. The 2^k bit indicates the
* presence of universe[k] in this set.
*/
private long elements = 0L;
EnumMap
1.key 必须是一个指定(构造器初始)的enum的实例,内部由数组实现,速度快
2.初始化后元素的顺序与enum实例定义顺序一致,其他操作与Map类似
3.实现 多路分发( multiple dispatching)
//命令模式 1.通常有一个仅有一个单一方法的接口
interface Command {
void action();
}
public class EnumMaps {
public static void main(String[] args) {
EnumMap<AlarmPoints, Command> em = new EnumMap<AlarmPoints, Command>(
AlarmPoints.class);
//em 的键只允许是初始化定义的 AlarmPoints.class 的实例
em.put(AlarmPoints.KITCHEN, new Command() {
// 命令模式 2. 从该接口实现有各自不同行为的 子实现
@Override
public void action() {
System.out.println("Kitchen Fire!");
}
});
em.put(AlarmPoints.BATHROOM, new Command() {
@Override
public void action() {
System.out.println("Bathroom Fire!");
}
});
for(Map.Entry<AlarmPoints,Command> e:em.entrySet()){
System.out.println(" e.getKey() " +e.getKey());
e.getValue().action();
}
try {
em.get(AlarmPoints.UTILITY).action();
} catch (Exception e ) {
e .printStackTrace();
}
}
}
常量指定方法 (constantspecific methods)
public enum ConstantSpecificMethod {
DATE_TIME {
String getInfo() {
return DateFormat.getDateInstance().format(new Date());
}
},
CLASSPATH {
String getInfo() {
return System.getenv("CLASSPATH");
}
},
VERSION {
String getInfo() {
return System.getProperty("java.version");
}
};
//声明一个抽象方法(或者普通方法——默认行为方法,后边再说)
abstract String getInfo();
public static void main(String[] args) {
for (ConstantSpecificMethod constantSpecMethod : values()) {
System.out.println("\\s"+constantSpecMethod.getInfo());
}
}
}
这个也称为表驱动的代码(详见< Code Complete>)。与命令模式很相似,只不过命令模式的通用接口,在这里由enum类代替。
oop不同类关联不同行为,而使用常量方法,每个实例就是一个独立的类型(当然,并不等同于“类”)。上例中一个enum类似乎被当作“超类”对待,具体到每个实例通过getInfo()表现出不同的行为,多态。
enum LikeClasses {
WINKEN { void behavior() { print("Behavior1"); } },
BLINKEN { void behavior() { print("Behavior2"); } },
NOD { void behavior() { print("Behavior3"); } };
abstract void behavior();
}
public class NotClasses {
// void f1(LikeClasses.WINKEN instance) {} // Nope
} /* Output:反编译后的代码
Compiled from "NotClasses.java"
abstract class LikeClasses extends java.lang.Enum{
public static final LikeClasses WINKEN;
public static final LikeClasses BLINKEN;
public static final LikeClasses NOD;
...
*///
1.abstract class LikeClasses extends java.lang.Enum 一个抽象类
2.方法常量 就是这个抽象类的static 域( field)
**其中的抽象方法也可以换做 普通方法,那么默认赋予每个enum实例一个默认的方法:
public enum ConstantSpecificMethod {
DATE_TIME, // 赋予默认 getInfo()
/*
* { String getInfo() { return DateFormat.getDateInstance().format(new
* Date()); } },
*/
CLASSPATH {
String getInfo() {
return System.getenv("CLASSPATH");
}
},
VERSION {
String getInfo() {
return System.getProperty("java.version");
}
};
String getInfo() {
System.out.println("default");
return null;
};
public static void main(String[] args) {
for (ConstantSpecificMethod constantSpecMethod : values()) {
System.out.println(constantSpecMethod.getInfo());
}
}
}