enum,EnumMap,EnumSet

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);
}
}
}

  1. 每个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());
        }
    }

}

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。