Java中enum跟int不一样,相当于两个不同的类型,不能相互转化,如果需要转换需要增加额外的方法。如果自己定义初值,并且希望可以根据数值在switch里面进行方便的比较,需要做一些特别的处理。
Enum的原型如下:
public abstract class Enum<E extends Enum<E>> implements Serializable, Comparable<E> {
private final String name;
private final int ordinal;
}
在Android\sdk\sources\android-17\java\lang\Enum.java 可以找到对应的源码。
其中,name就是你定义的枚举的名字,如EStudent、ETeacher等。ordinal按照你定义的先后顺序顺次排列,值为0、1、2...。
需要注意的是,android里面Enum类型是不能被继承的,而且重写起来也非常困难,比如需要BasicLruCache.java、EmptyArray.java、Class.java等诸多文件,而Class.java又引用了很多的包,比如:
import sun.misc.Unsafe;
import sun.reflect.ConstantPool;
import sun.reflect.Reflection;
import sun.reflect.ReflectionFactory;
import sun.reflect.SignatureIterator;
import sun.reflect.generics.factory.CoreReflectionFactory;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.repository.ClassRepository;
import sun.reflect.generics.repository.MethodRepository;
import sun.reflect.generics.repository.ConstructorRepository;
import sun.reflect.generics.scope.ClassScope;
import sun.security.util.SecurityConstants;
import sun.reflect.annotation.*;
......
因此,要重写一个MyEnum替代enum是比较困难的:
public abstract class MyEnum<E extends MyEnum<E>> implements Serializable, Comparable<E> {
}
但是要达到上述目的却是可以的,看下面的例子。
这是用户的期望:
int val = 2;
MyEnum type = EnumUtils.getMyEnum(MyEnum.class, val);
val = 10;
MyEnum defaultType = MyEnum.EUnknown;
type = EnumUtils.getMyEnum(MyEnum.class, val, defaultType);
switch(type) {
case EUnknown:
break;
case EStudent:
break;
case STeacher:
break;
}
在实际项目中,MyEnum 的枚举值可能是这样的:
public enum MyEnum {
EUnknown(0),
EStudent(2),
STeacher(3);
}
甚至是这样的DataType:
ENewsText(0x1001),
ENewsWithSlide(0x1002),
ENewsWithVideo(0x1003),
ENewsComment(0x1004),
EMatch(0x2000), //比赛,小于0x2000的是新闻
EMatchLiveVideoPresent(0x2001),
EMatchLiveTextPresent(0x2002),
EMatchOver(0x2003),
EMatchLiveVideoDNS(0x2004),
EMatchLiveTextDNS(0x2005),
因此,首先需要实现赋初值(private):
int val;
MyEnum(int val) {
this.val = val;
}
其次,要实现int与enum的转换。
enum转换为int,非常简单,只需要注意到val与ordinal的不同:
public int getVal() {
return val;
}
最后,要实现int转换为enum,强大的Java当然不会傻瓜到需要你通过switch(val)的方式返回不同的enum值,可以通过如下的方式:
public static <T extends Enum<T>> T getMyEnum(Class<T> enumType, int val) {
return getMyEnum(enumType, val, null);
}
public static <T extends Enum<T>> T getMyEnum(Class<T> enumType, int val, T defaultVal) {
return getMyEnum(enumType, "val", val, defaultVal); //T定义了int val;字段
}
public static <T extends Enum<T>> T getMyEnum(Class<T> enumType, String fieldName, Object fieldVal) {
return getMyEnum(enumType, fieldName, fieldVal, null);
}
public static <T extends Enum<T>> T getMyEnum(Class<T> enumType, String fieldName, Object fieldVal, T defaultVal) {
T ret = defaultVal;
try {
T[] myEnums = enumType.getEnumConstants();
Field fl = enumType.getDeclaredField(fieldName);
if(myEnums != null && myEnums.length > 0) {
for(T t : myEnums) {
try {
if(fieldVal == fl.get(t)) {
ret = t;
break;
}
} catch (IllegalArgumentException e) {
// e.printStackTrace();
} catch (IllegalAccessException e) {
// e.printStackTrace();
}
}
}
} catch (NoSuchFieldException e) {
// e.printStackTrace();
} catch(NullPointerException e) {
// e.printStackTrace();
}
return ret;
}
当然,如果你用的枚举类型比较少,而且划分的枚举段非常清晰的话,也可以用简易的方式:
public DataType getType(int value) {
int index = 0;
if(value < EMatch.getValue()) {
index = value - ENews.getValue();
} else {
index = value - EMatch.getValue();
}
if(index >= 0 && index < DataType.values().length) {
return DataType.values()[index];
} else {
return ENews; //defaultVal
}
}
其他资料可以参考:http://blog.csdn.net/lz12366007/article/details/4729781
中间的要点有:
Java中的枚举是在JDK1.5才引进的,使用enum为关键字,是一种新的类型,允许用常量来表示数据片断。所有的枚举类型都是java.lang.Enum类的子类,枚举内的常量用‘,’分隔开,若后面还有语句,则最后一个常量后面要用‘;’,枚举中的常量默认都是public static final,这就是为什么枚举中的常量建议全大写的原因,虽然它默认是public static final,但你在声明常量时却不能显式使用public static final,否则编译器反而会报错误。枚举常量实际就是格举类型的实例,它的初始化是依靠java.lang.Enum类的构造方法来的。第一个枚举常量的值默认是0,其它的依次加1.
枚举类型不能使用extends关键字,但是可以使用implements关键字。这样我们可以把不同枚举类型共有的行为提取到接口中,来规范枚举类型的行为。
枚举类型的自定义构造函数并不能覆盖默认执行的构造函数,它会跟在默认构造函数之后执行。
枚举类型的自定义构造函数必须是私有的,可以显式加private。
枚举类型中枚举常量的定义必须放在最上面,其后才能是变量和方法的定义。
使用举例:
//自定义枚举类型的接口
public interface EnumInterface {
public int getValue();
public <T> T getEnum(int val);
public <T extends Enum<T>> T getDefaultValue();
}
在枚举DataType 中实现接口:
private final int val;
@Override
public int getValue() {
return val;
}
@SuppressWarnings("unchecked")
@Override
public <T> T getEnum(int val) {
DataType defaultT = getDefaultValue();
return (T) EnumUtils.getMyEnum(DataType.class, val, defaultT);
}
@SuppressWarnings("unchecked")
@Override
public <T extends Enum<T>> T getDefaultValue() {
return (T) ENews;
}