Enum+多态,我没说错,不过Enum是不可以被继承的,也不可以继承自别人,只是能实现接口而已,何谈多态?
不过还是先看看“现象”吧:
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.");
}
}
其中,只有Orange没有Overide 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文件??也许看到这里我们能有点线索了,不过还是在这个时候在看看反编译结果吧,看看它到底在搞什么鬼:
// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3)
// Source File Name: Fruit.java
package test;
import java.io.PrintStream;
public class Fruit extends Enum
{
private Fruit(String s, int i)
{
super(s, i);
}
public void test()
{
System.out.println("I am a fruit.");
}
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);
}
Fruit(String s, int i, Fruit fruit)
{
this(s, i);
}
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) {
public void test()
{
System.out.println("I am an apple.");
}
};
PEAR = new Fruit("PEAR", 1) {
public void test()
{
System.out.println("I am a pear.");
}
};
PEACH = new Fruit("PEACH", 2) {
public void test()
{
System.out.println("I am a peach.");
}
};
ORANGE = new Fruit("ORANGE", 3);
ENUM$VALUES = (new Fruit[] {
APPLE, PEAR, PEACH, ORANGE
});
}
}
注意这段代码:
static
{
APPLE = new Fruit("APPLE", 0) {
public void test()
{
System.out.println("I am an apple.");
}
};
PEAR = new Fruit("PEAR", 1) {
public void test()
{
System.out.println("I am a pear.");
}
};
PEACH = new Fruit("PEACH", 2) {
public void test()
{
System.out.println("I am a peach.");
}
};
ORANGE = new Fruit("ORANGE", 3);
这个时候的APPLE,PEAR,PEACH已经以匿名内部类的方式对Fruit进行了Overide,自然体现出了多态,多出的那三个疑似内部类的class文件也就是它们!而ORANGE,没有重写test方法,仍然以一个Fruit实例的形式出现。
关于Enum为什么会有多态大概也就这么点猫腻了,那我们来考虑一下它有多大价值吧?
我们或许可以利用这一点来改造Strategy模式,传统的Strategy会产生出稍微多一些的父类、子类,而如果用Enum的话,“一个类”(对程序作者来讲)就能搞定,能简化一下类层次,再说了,用枚举来表示区分各种不同策略也是很合情理的,所以,Java Enum的这点小小特性感觉还是比较有前途发挥一些作用的,起码在代码组织上;
更多应用可能或是局限性就还需要逐步在实际应用中摸索。
分享到:
相关推荐
java enum详细教程。由浅入深,包括基本语法方面..很适合新手学习。/n各位看官。绝对超值。
Java enum的用法详解,可作为开发api
博文“Java 语言中 Enum 类型的使用介绍”的源码。
Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类...
ava enum 枚举的spring boot2.x完美实现demo源码。java的枚举类型,可以理解为一种特殊的java类
java中enum枚举的详细用法。 0.0
enum李兴华视频笔记,绝对值得看!
Java enum的用法详解
java enum枚举教程学习资料
javaenum学习.pdf
Java中的Enum的使用与分析
NULL 博文链接:https://rensanning.iteye.com/blog/2013734
主要介绍了Java Enum和String及int的相互转化示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
java枚举类型的定义使用介绍,还有示例。
java代码-java enum枚举遍历
Java ---- enum --- 枚举类案例
NULL 博文链接:https://janeky.iteye.com/blog/463611
简单查询算法,供学习参考。 代码中描述了Enum和EnumMap类的使用。