Enum 多态,我没说错,不过Enum是不可以被继承的,也不可以继承自别人,只是能实现接口而已,何谈多态?
不过还是先看看“现象”吧:
Java代码
public enum Fruit {
APPLE, PEAR, PEACH, ORANGE;
}
以上是一个简单的enum,关于它,我要补充一点:
Fruit是java.lang.Enum的子类,准确地说,是Enum<Fruit>的子类,这里出现了一个继承关系,不过这个继承是编译器帮我们做的,我们不能显式地去做。不信的话我们可以试着用一个Enum<Fruit>的引用去指向一个APPLE,肯定是没问题的,我就不再试了。
为了更直观地说明这一点,我们来看看Fruit的反编译结果吧:
package test;
public final class Fruit extends Enum {
private Fruit(String s, int i) {
super(s, i);
}
public static Fruit[] values() {
Fruit afruit[];
int i;
Fruit afruit1[];
System.arraycopy(afruit = ENUM$VALUES, 0,
afruit1 = new Fruit[i = afruit.length], 0, i);
return afruit1;
}
public static Fruit valueOf(String s) {
return (Fruit) Enum.valueOf(test / Fruit, s);
}
public static final Fruit APPLE;
public static final Fruit PEAR;
public static final Fruit PEACH;
public static final Fruit ORANGE;
private static final Fruit ENUM$VALUES[];
static {
APPLE = new Fruit("APPLE", 0);
PEAR = new Fruit("PEAR", 1);
PEACH = new Fruit("PEACH", 2);
ORANGE = new Fruit("ORANGE", 3);
ENUM$VALUES = (new Fruit[] { APPLE, PEAR, PEACH, ORANGE });
}
}
注意这几行:
public static final Fruit APPLE;
public static final Fruit PEAR;
public static final Fruit PEACH;
public static final Fruit ORANGE;
看来JDK Enum的实现也不过就是沿袭了Effective Java中提出的TypeSafeEnum模式,只不过是在编译器和JVM等更底层的级别上提供了支持。
至此,至少说明了Fruit和Enum的继承关系,但问题是:现在不能继续再从Fruit派生子类,那么哪来的多态呢?
还是再多写点代码吧:
public enum Fruit {
APPLE {
public void test() {
System.out.println("I am an apple.");
}
},
PEAR {
public void test() {
System.out.println("I am a pear.");
}
},
PEACH {
public void test() {
System.out.println("I am a peach.");
}
},
ORANGE;
public void test() {
System.out.println("I am a fruit.");
}
}
public enum Fruit {
APPLE {
public void test() {
System.out.println("I am an apple.");
}
},
PEAR {
public void test() {
System.out.println("I am a pear.");
}
},
PEACH {
public void test() {
System.out.println("I am a peach.");
}
},
ORANGE;
public void test() {
System.out.println("I am a fruit.");
}
}
其中,只有Orange没有Overide test()方法;
我们在主函数中调用它们:
public static void main(String[] args) {
Fruit.APPLE.test();
Fruit.PEAR.test();
Fruit.PEACH.test();
Fruit.ORANGE.test();
} public static void main(String[] args) {
Fruit.APPLE.test();
Fruit.PEAR.test();
Fruit.PEACH.test();
Fruit.ORANGE.test();
}
输出结果:
引用
I am an apple.
I am a pear.
I am a peach.
I am a fruit.
可以看到,重新定义了test方法的APPLE,PEAR,PEACH覆盖了从父类继承过来的默认行为,而未从新定义test方法的ORANGE却沿袭了父类的行为,多态性在这里展现出来了。
那么我们刚才明明看见过Fruit的反编译结果,没有任何新类继承自Fruit,那么这些多态行为是哪里冒出来的呢?说它是“多态”是否准确呢?
其实,Fruit类在这个时候已经发生了微妙的变化,一切都与JDK的Enum的实现有关,我们现在可以到编译结果目录下面看看:
怎么除了Fruit.class之外,还多了几个貌似是内部类的class文件??也许看到这里我们能有点线索了,不过还是在这个时候在看看反编译结果吧,看看它到底在搞什么鬼: