学习JDK5的枚举类型

昨天晚上在给Struts2的Action写测试代码的时候,需要用到enum,就研究了一下。
先是enum的代码:
代码段1:
public enum ActionResult {

SUCCESS("success"),
NONE("none"),
ERROR("error"),
INPUT("input"),
LOGIN("login");

private String value;

private ActionResult(String value){
this.value = value;
}

/**
* 返回常量值
* @return 常量值
*/
public String getValue(){
return value;
}
}

试着输出ActionResult.SUCCESS:
System.out.println(ActionResult.SUCCESS);

结果:
[quote]SUCCESS[/quote]

输出ActionResult.SUCCESS.getClass():
System.out.println(ActionResult.SUCCESS.getClass());

结果:
[quote]class net.javayuan.blog.constant.ActionResult[/quote]

给ActionResult加上main方法,检查ActionResult的类型:

public enum ActionResult {

SUCCESS("success"),
NONE("none"),
ERROR("error"),
INPUT("input"),
LOGIN("login");

private String value;

private ActionResult(String value){
this.value = value;
}

/**
* 返回常量值
* @return 常量值
*/
public String getValue(){
return value;
}

public static void main(String[] args){
Class<?> clazz = ActionResult.class;
Class<?> superClass = clazz.getSuperclass();
Class<?>[] interfaces = clazz.getInterfaces();
System.out.println(clazz);
System.out.println(superClass);
System.out.println(interfaces.length);
}
}

输出:
[quote]class net.javayuan.blog.constant.ActionResult
class java.lang.Enum
0[/quote]
结论:1、enum关键字定义的枚举类型的直接父类都是java.lang.Enum。至于Enum的父类,查查API文档就知道了:Enum的父类是Object。
2、enum关键字定义的枚举类型没有直接实现任何接口。查了API文档,Enum实现了Serializable接口跟Comparable接口。
已知:ActionResult.SUCCESS.getClass().toString()的结果是"class net.javayuan.blog.constant.ActionResult",
并且ActionResult的父类是Enum,接着来看看为什么System.out.println(ActionResult.SUCCESS);输出"SUCCESS"。

打开java.lang.Enum的源代码,查找关键字“public String toString()”,找到代码:
public String toString() {
return name;
}


name的定义:
private final String name;

name的赋值在Enum的protected构造方法中执行:
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}

给ActionResult的main方法中添加一句代码:System.out.println(ActionResutl.SUCCESS)
	public static void main(String[] args){
Class<?> clazz = ActionResult.class;
Class<?> superClass = clazz.getSuperclass();
Class<?>[] interfaces = clazz.getInterfaces();
System.out.println(clazz);
System.out.println(superClass);
System.out.println(interfaces.length);

System.out.println(ActionResult.SUCCESS);
}

在Enum的构造方法处和ActionResult的main方法处同时设置断点,检查Enum的构造是在什么时候执行。结果用Eclipse调试的时候意外的发现,Enum的构造在main方法执行之前。查看Enum构参数中name和ordinal的值,居然name为null,那toString中的name是怎么来的?继续调试,发现执行完this.name = name;之后,参数列表中的name跟Enum中的name同时变成了"SUCCESS",这个值是怎么来的,我也无从查证,因为构造Enum时,参数name居然是未知的,我只能猜测是JVM对Enum进行了特殊处理。再调试了几遍,发现第二个构造参数ordinal也一样(它也是Enum类的一个私有int常量),执行this.ordinal = ordinal;之后,它的值才确定。按F7跳出Enum的构造方法,结果跳到ActionResult的构造方法里,检查参数value,值为"success"。按F7,跳到了SUCCESS("success");这一行。按F5,发现SUCCESS("success")刚执行完毕,原来刚刚的动作是对SUCCESS进行初始化。现在箭头指在NONE("none")这一行,按F5,进入ActionResult构造方法,再按F5,进入了Enum构造方法,执行完Enum的构造,检查一下ordinal的值,为1。初始化ERROR时,ordinal为2。
结论:
1、SUCCESS、NONE等静态变量是常量;
2、ActionResult的构造是在对常量SUCCESS、NONE等进行初始化时执行,每个常量都是一个ActionResult实例;
3、ActionResult构造之前会调用Enum的构造方法,对Enum进行构造(看来之前写的[url="http://yuan.iteye.com/blog/222656"]关于构造方法[/url]对enum不适用);
4、构造Enum时,参数name和ordinal的值都是未知的,name值似乎是来自常量名,ordinal从0开始递增,ordinal具体作用目前不明;

翻了Thinking In Java 4th Edition:
[quote]ordinal()方法返回一个int值,这是每个enum实例在声明时的次序,从0开始。[/quote]
[quote]values()是由编译器添加的static方法。可以看出,在创建Explore的过程中,编译器还为其添加了valueOf()方法。这可能有点令人迷惑,Enum类不是已经有valueOf()方法了吗。不过Enum中的valueOf()方法需要两个参数,而这个新增的方法只需要一个参数。[/quote]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值