JAVA中的枚举类型

提要:

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在内部表现为数组。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值