您的位置:首页 > 编程语言 > Java开发

JAVA中的枚举类型

2016-05-25 17:54 381 查看
提要:

1.枚举类型介绍与简单使用

2.枚举类型中常用的方法

3.枚举类型嵌套

4.EnumSet与EnumMap

1.枚举类型介绍与简单使用

从java 1.5开始有的枚举类型,基本使用方法是用enum关键字定义。
创建enum时,编译器会为你生成一个相关的类,这个类继承自Enum,在这个类里每个枚举实例都是一个static final的LikeClasses类的对象。
除了不能继承之外,enum拥有几乎所有类的特性,比如说它可以添加成员变量成员方法和构造方法(构造方法只能是private),并且为它们使用修饰符(默认是default范围)。

之所以提倡使用枚举而不是static final变量这种形式的常量,是因为常量①可读性不好②无法保证类型安全

示例:
public enum Test{
T1("1"),T2("2");

static String s1 = "s1";
static String s2 = "s2";
Test(String s){
System.out.println(s);
print();
}
public static void plus(){
System.out.println(s1 + s2);
}
private void print(){
System.out.printf("%s,%s\n",s1,s2);
}
}
public static void main(String[] args){
Test test = Test.T1;
test.plus();
switch (test) {
case T1 :
System.out.println(true);
break;

default :
System.out.println(true);
break;
}
}

----------------------------
输出结果:
1
null,null
2
null,null<pre name="code" class="java">s1s2
true

之所以会是null是因为static变量直到它所属的类第一次被加载时才会被加载,这里只是编译并没有使用,类没有被加载


2.枚举类型中常用的方法

调用values()方法,可以遍历enum实例。
调用toString()方法,可以打印枚举实例的名称。
调用valueOf()方法,可以根据名字获得枚举实例。
调用ordinal()方法,可以取得枚举实例的次序。

举个栗子:
public class Test {

public enum Fruit{
APPLE,ORANGE,TOMATO;

}

public static void main(String[] args){

for(Fruit fruit : Fruit.values()){
System.out.println(fruit.toString() + " is on " + fruit.ordinal());
}

System.out.println("It's " + Fruit.valueOf("APPLE").toString());
}

}
------------------------------------
输出:
APPLE is on 0
ORANGE is on 1
TOMATO is on 2
It's APPLE


3.枚举类型嵌套

枚举并不支持继承,但有时候会遇到这种情况:想要把多个枚举类型进行分组,并且使它们之间具有层次结构。比如:

Food:{
DESSERT:{VEGETABLES, CAPCAKE},
COFFEE:{LATEE, TEA}
}
或许我可以建一个这样的枚举?

public class Test{

enum Food{
DESSERT(Dessert.class), COFFEE(Coffee.class);

private Enum[] food;
private Food(Class<?> eclass) {
this.food = (Enum[]) eclass.getEnumConstants();
}

public Enum[] getFood(){
return food;
}
}

enum Dessert{
VEGETABLES, CAPCAKE
}

enum Coffee{
LATTE, TEA
}

public static void main(String args[]) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{
Enum[] enums = Food.DESSERT.getFood();
for(Enum e : enums){
System.out.println(e.ordinal());
System.out.println(e.toString());
}
}
}


重点在于Class的getEnumConstants方法,该方法专用于枚举类型,返回其枚举实例。但这种方式并没有直观的组织化,Dessert和Coffee并没有在语法上归为同一类,Food的枚举实例也可以接受除了这两个枚举之外的任何枚举类型参数。因此考虑用interface作为中介,使Dessert和Coffee实现同一个接口,并且Food只接受这个接口的实现类:

public class Test{

public interface FoodIntef{

public enum Dessert implements FoodIntef{
VEGETABLES, CAPCAKE
}

public enum Coffee implements FoodIntef{
LATTE, TEA
}

}

public enum Food{
DESSERT(FoodIntef.Dessert.class), COFFEE(FoodIntef.Coffee.class);

private FoodIntef[] food;
private Food(Class<? extends FoodIntef> food){
this.food = food.getEnumConstants();
}
}
}


4.EnumSet和EnumMap

EnumSet是专用于存储枚举类型的set,其中的所有键都必须来自同一个枚举类型。枚举实例在EnumSet内部以位向量的形式存储,因此非常紧凑和高效。

和大多数集合类一样,EnumSet是不同步的。

EnumSet通过自身的多个静态方法创建实例。其中EnumSet有多个重载的of方法,在枚举实例个数为2~5个时候都可以使用固定参数的of方法,超过5个则使用可变参数的of方法,这样做的原因是可变参数对比显式的参数,在性能上会有一点损失。

EnumSet的底层实现是long,一个long值占64位空间,而一个enum实例只需一个bit位表示其是否存在,如果enum元素多过64个bit,EnumSet会用一个

new long[(universe.length + 63) >>> 6]

EnumMap用来自同一个枚举类型的枚举实例作为键,除了键只能是枚举类型这一个限制,其他跟Map差不多。

EnumMap在内部表现为数组。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: