Java 枚举7常见种用法
http://softbeta.iteye.com/blog/1185573
DK1.5引入了新的类型——枚举。在Java中它虽然算个“小”功能,却给我的开发带来了“大”方便。
用法一:常量
在JDK1.5之前,我们定义常量都是:public static fianl....。现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。
- public enum Color {
- RED, GREEN, BLANK, YELLOW
- }
用法二:switch
JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。
- enum Signal {
- GREEN, YELLOW, RED
- }
- public class TrafficLight {
- Signal color = Signal.RED;
- public void change() {
- switch (color) {
- case RED:
- color = Signal.GREEN;
- break;
- case YELLOW:
- color = Signal.RED;
- break;
- case GREEN:
- color = Signal.YELLOW;
- break;
- }
- }
- }
用法三:向枚举中添加新方法
如果打算自定义自己的方法,那么必须在enum实例序列的最后添加一个分号。而且Java要求必须先定义enum实例。
- public enum Color {
- RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
- // 成员变量
- private String name;
- private int index;
- // 构造方法
- private Color(String name, int index) {
- this.name = name;
- this.index = index;
- }
- // 普通方法
- public static String getName(int index) {
- for (Color c : Color.values()) {
- if (c.getIndex() == index) {
- return c.name;
- }
- }
- return null;
- }
- // get set 方法
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getIndex() {
- return index;
- }
- public void setIndex(int index) {
- this.index = index;
- }
- }
用法四:覆盖枚举的方法
下面给出一个toString()方法覆盖的例子。
- public enum Color {
- RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
- // 成员变量
- private String name;
- private int index;
- // 构造方法
- private Color(String name, int index) {
- this.name = name;
- this.index = index;
- }
- //覆盖方法
- @Override
- public String toString() {
- return this.index+"_"+this.name;
- }
- }
用法五:实现接口
所有的枚举都继承自java.lang.Enum类。由于Java不支持多继承,所以枚举对象不能再继承其他类。
- public interface Behaviour {
- void print();
- String getInfo();
- }
- public enum Color implements Behaviour{
- RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
- // 成员变量
- private String name;
- private int index;
- // 构造方法
- private Color(String name, int index) {
- this.name = name;
- this.index = index;
- }
- //接口方法
- @Override
- public String getInfo() {
- return this.name;
- }
- //接口方法
- @Override
- public void print() {
- System.out.println(this.index+":"+this.name);
- }
- }
用法六:使用接口组织枚举
- public interface Food {
- enum Coffee implements Food{
- BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO
- }
- enum Dessert implements Food{
- FRUIT, CAKE, GELATO
- }
- }
用法七:关于枚举集合的使用
java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的key是enum类型,而value则可以是任意类型。关于这个两个集合的使用就不在这里赘述,可以参考JDK文档。
关于枚举的实现细节和原理请参考:
参考资料:《ThinkingInJava》第四版
java枚举类型
http://www.cnblogs.com/Fskjb/archive/2009/08/03/1537917.htmlpublic class TestEnum {
/*最普通的枚举*/
public enum ColorSelect {
red, green, yellow, blue;
}
/* 枚举也可以象一般的类一样添加方法和属性,你可以为它添加静态和非静态的属性或方法,这一切都象你在一般的类中做的那样. */
public enum Season {
// 枚举列表必须写在最前面,否则编译出错
winter, spring, summer, fall;
private final static String location = "Phoenix";
public static Season getBest() {
if (location.equals("Phoenix"))
return winter;
else
return summer;
}
}
/*还可以有构造方法*/
public enum Temp {
/*通过括号赋值,而且必须有带参构造器和一属性跟方法,否则编译出错
* 赋值必须是都赋值或都不赋值,不能一部分赋值一部分不赋值
* 如果不赋值则不能写构造器,赋值编译也出错*/
absoluteZero(-459), freezing(32),boiling(212), paperBurns(451);
private final int value;
public int getValue() {
return value;
}
//构造器默认也只能是private, 从而保证构造函数只能在内部使用
Temp(int value) {
this.value = value;
}
}
public static void main(String[] args) {
/*
* 枚举类型是一种类型,用于定义变量,以限制变量的赋值 赋值时通过"枚举名.值"来取得相关枚举中的值
*/
ColorSelect m = ColorSelect.blue;
switch (m) {
/*注意:枚举重写了ToString(),说以枚举变量的值是不带前缀的
*所以为blue而非ColorSelect.blue
*/
case red:
System.out.println("color is red");
break;
case green:
System.out.println("color is green");
break;
case yellow:
System.out.println("color is yellow");
break;
case blue:
System.out.println("color is blue");
break;
}
System.out.println("遍历ColorSelect中的值");
/*通过values()获得枚举值的数组*/
for (ColorSelect c : ColorSelect.values()) {
System.out.println(c);
}
System.out.println("枚举ColorSelect中的值有:"+ColorSelect.values().length+"个");
/*ordinal()返回枚举值在枚举中的索引位置,从0开始*/
System.out.println(ColorSelect.red.ordinal());//0
System.out.println(ColorSelect.green.ordinal());//1
System.out.println(ColorSelect.yellow.ordinal());//2
System.out.println(ColorSelect.blue.ordinal());//3
/*枚举默认实现了java.lang.Comparable接口*/
System.out.println(ColorSelect.red.compareTo(ColorSelect.green));
System.out.println(Season.getBest());
for(Temp t:Temp.values()){
/*通过getValue()取得相关枚举的值*/
System.out.println(t+"的值是"+t.getValue());
}
}
}
一步步构造int型枚举
http://www.189works.com/article-18597-1.html
在Java 1.5之前,我们经常会把类型、状态、性别等取值范围很小而且比较固定的数据存储为int型常量,在枚举类型出现之前,大家都不会觉得有什么不便,然而在枚举类型出现之后,这种方式的缺点就明显了,一个是不可罗列,另一个是弱类型。然而int型仍然有int型的好处,比如持久化存储、位运算都要比枚举类型更加方便,所以如果有一种方式能够把两者综合一下就好了,下面我就介绍一种把两者结合起来的小技巧。
“int型枚举”是为了简化概念取的一个名字,并不是很准确,姑且这样一叫吧,觉得名字不好并且恰好手里有砖的可以拍了。
首先我们声明一个接口,以方便标识“int型枚举”这个抽象概念,接口里定义一个toInt()方法,用以将枚举对象转化成int值:
public interface IntEnum {
int toInt();
}
现在我们用Sex类为例来实现这个IntEnum接口:
public enum Sex implements IntEnum {
MALE {
@Override
public int toInt()
{
return 1;
}
},
FEMALE {
@Override
public int toInt()
{
return 2;
}
}
}
OK,从代码里我们可以看出,MALE转化成int是1,FEMALE是2(当然有人说MALE为1,FEMALE为0更形象,我想说,你太猥琐了)。
下面要做的是实现是从int到Sex的逆向转化,有经验的同学已经想到了,对,没错,我们只需要构造一个int到Sex的Map映射问题就解决了,为了让代码尽可能的复用,我们把这个方法写在一个工具类里,JDK针对特定类型的工具类都喜欢以[针对的类型s]的方式命名,所以我们也随大流,就叫IntEnums(如果你不知道泛型相关的知识,请自行翻书):
public class IntEnums {
public static <T extends Enum<T> & IntEnum> Map<Integer, T> map(Class<T> clazz)
{
Map<Integer, T> instanceMap = new HashMap<Integer, T>();
EnumSet<T> values = EnumSet.allOf(clazz);
for(T value : values)
{
instanceMap.put(value.toInt(), value);
}
return instanceMap;
}
}
现在工具类建好了,该考虑转化操作怎么搞才方便用的问题了,我们知道Enum都有一个valueOf方法,用于把字符串直接转化成Enum对象,我们可以借用这个方法名,重载它,实现IntEnum从int到枚举的转化,所以Sex的最终代码如下:
public enum Sex implements IntEnum {
MALE {
@Override
public int toInt()
{
return 1;
}
},
FEMALE {
@Override
public int toInt()
{
return 2;
}
};
private static Map<Integer, Sex> instanceMap = IntEnums.map(Sex.class);
public static Sex valueOf(int i)
{
return instanceMap.get(i);
}
}
当然,有的同学可能想到,把转化过程完全封装在IntEnums里不是更好,这种想法是好的,然而一并考虑到并发安全、效率等问题,可能变得有些复杂,当然如果大家有更好的做法,请尽情发挥。