1.楔子
枚举能继承别枚举吗?枚举能继承其他类吗?枚举能实现接口吗?枚举能被其他类继承吗?
本文就是要探讨这些问题。
2. 准备
本文需要使用到反编译,请自行安装Jad(JAva Decompiler)反编译工具。由于该工具最新的版本也只支持Java 4,不支持Java 5,所以能够很好的保留jdk5之后的例如枚举等原生的编译结果。
jad的使用教程:Java反编译工具Jad详解
JD-GUI反编译工具支持枚举,更高级,更强大,所以反编译的结果与源码基本一致,所以反编译是看不到JAVA编译的处理结果。
3. 枚举反编译
枚举源代码如下:
public enum ErrorCode {
SUCCESS(1);
private int code;
ErrorCode(int code) {
this.code = code;
}
}
执行jad -sjava ErrorCode.class (指定生成源代码的后缀名:-sjava)。
反编译结果:
package com.sino.daily.code_2019_4_24;
public final class ErrorCode extends Enum
{
//编译器为我们添加的静态的values()方法
public static ErrorCode[] values()
{
return (ErrorCode[])$VALUES.clone();
}
//编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法
public static ErrorCode valueOf(String name)
{
return (ErrorCode)Enum.valueOf(com/sino/daily/code_2019_4_24/ErrorCode, name);
}
//私有构造函数,被改写,加入了s-name和i-ordinal
private ErrorCode(String s, int i, int code)
{
super(s, i);
this.code = code;
}
// 前面定义的枚举实例
public static final ErrorCode SUCCESS;
private int code;
private static final ErrorCode $VALUES[];
//实例化枚举实例
static
{
SUCCESS = new ErrorCode("SUCCESS", 0, 1);
// 获取到所有的枚举实例对象最为values
$VALUES = (new ErrorCode[] {
SUCCESS
});
}
}
public final class ErrorCode extends Enum看出该类是继承自java.lang.Enum类(该类是一个抽象类public abstract class Enum<E extends Enum<E>>), 故不能再继承其他类,而且类时final的,所以也不能被其他类继承。- 编译器为我们生成了ErrorCode类的对象
public static final ErrorCode SUCCESS作为枚举实例,并进行初始化SUCCESS = new ErrorCode("SUCCESS", 0, 1)。初始化时额外增加了两个参数s-name(举常量的名称)和i-ordinal(枚举常量的序数,其中初始常量序数为零)。
- 如果枚举实例的声明位置发生变化,那么ordinal方法获取到的值也随之变化,注意在大多数情况下我们都不应该首先使用该方法,毕竟它总是变幻莫测的。
valueOf(String name)方法的作用是根据名称获取枚举变量,采用了Enum类中的valueOf方法,调用方式为:(ErrorCode)Enum.valueOf(com/sino/daily/code_2019_4_24/ErrorCode, name), 入参是枚举类和枚举实例名,主要实现思路是采用反射,获取到所有的实例对象(调用values方法)放入MAP<实例名, 实例对象>中,然后从MAP中取。
4.enum类中定义抽象方法
与常规抽象类一样,enum类允许我们为其定义抽象方法,然后使每个枚举实例都实现该方法,以便产生不同的行为方式,注意abstract关键字对于枚举类来说并不是必须的如下:
public enum Operation{
ADD {
@Override
public int eval(int arg1, int arg2) { return arg1 + arg2; };
},
SUBTRACT {
@Override
public int eval(int arg1, int arg2) { return arg1 - arg2; };
};
//定义抽象方法
public abstract int eval(int arg1, int arg2);
public static void main(String[] args) {
System.out.println(Operation.ADD.eval(1,2));
System.out.println(Operation.SUBTRACT.eval(1,2));
}
}
通过这种方式就可以轻而易举地定义每个枚举实例的不同行为方式。我们可能注意到,enum类的实例似乎表现出了多态的特性,但这并非真正的多态。
同样进行反编译,反编译后发现多了几个内部类。
Operation$1的反编译结果为:
每个重载了eval的枚举实例都对应了一个匿名内部类。
5. enum类与接口
由于Java单继承的原因,enum类并不能再继承其它类,但并不妨碍它实现接口,因此enum类同样是可以实现多接口的。
6.参考文献
来源:CSDN
作者:jieniyimiao
链接:https://blog.csdn.net/u013467442/article/details/89499091

