小谈Java Enum的多态性
2015-08-02 08:10
567 查看
Enum+多态,我没说错,不过Enum是不可以被继承的,也不可以继承自别人,只是能实现接口而已,何谈多态?
不过还是先看看“现象”吧:
Fruit是java.lang.Enum的子类,准确地说,是Enum<Fruit>的子类,这里出现了一个继承关系,不过这个继承是编译器帮我们做的,我们不能显式地去做。不信的话我们可以试着用一个Enum<Fruit>的引用去指向一个APPLE,肯定是没问题的,我就不再试了。
为了更直观地说明这一点,我们来看看Fruit的反编译结果吧:
至此,至少说明了Fruit和Enum的继承关系,但问题是:现在不能继续再从Fruit派生子类,那么哪来的多态呢?
还是再多写点代码吧:
我们在主函数中调用它们:
那么我们刚才明明看见过Fruit的反编译结果,没有任何新类继承自Fruit,那么这些多态行为是哪里冒出来的呢?说它是“多态”是否准确呢?
其实,Fruit类在这个时候已经发生了微妙的变化,一切都与JDK的Enum的实现有关,我们现在可以到编译结果目录下面看看:
![](http://pf-miles.iteye.com/upload/picture/pic/12981/8d59eac5-4fd3-3248-9efe-dfc89cc1e01d.png)
怎么除了Fruit.class之外,还多了几个貌似是内部类的class文件??也许看到这里我们能有点线索了,不过还是在这个时候在看看反编译结果吧,看看它到底在搞什么鬼:
关于Enum为什么会有多态大概也就这么点猫腻了,那我们来考虑一下它有多大价值吧?
我们或许可以利用这一点来改造Strategy模式,传统的Strategy会产生出稍微多一些的父类、子类,而如果用Enum的话,“一个类”(对程序作者来讲)就能搞定,能简化一下类层次,再说了,用枚举来表示区分各种不同策略也是很合情理的,所以,Java Enum的这点小小特性感觉还是比较有前途发挥一些作用的,起码在代码组织上;
更多应用可能或是局限性就还需要逐步在实际应用中摸索。
转自:小谈Java Enum的多态性
不过还是先看看“现象”吧:
package cn.itcast.domain; public enum Fruit { APPLE, PEAR, PEACH, ORANGE; }以上是一个简单的enum,关于它,我要补充一点:
Fruit是java.lang.Enum的子类,准确地说,是Enum<Fruit>的子类,这里出现了一个继承关系,不过这个继承是编译器帮我们做的,我们不能显式地去做。不信的话我们可以试着用一个Enum<Fruit>的引用去指向一个APPLE,肯定是没问题的,我就不再试了。
为了更直观地说明这一点,我们来看看Fruit的反编译结果吧:
package cn.itcast.domain; 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派生子类,那么哪来的多态呢?
还是再多写点代码吧:
package cn.itcast.domain; 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的实现有关,我们现在可以到编译结果目录下面看看:
![](http://pf-miles.iteye.com/upload/picture/pic/12981/8d59eac5-4fd3-3248-9efe-dfc89cc1e01d.png)
怎么除了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 cn.itcast.domain;
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的多态性
相关文章推荐
- 定制Eclipse IDE之插件篇(二)
- [Drools]JAVA规则引擎 -- Drools
- java反射详解
- 定制Eclipse IDE之插件篇(一)
- Java nio Netty实现基本的收发包
- java基础之用linkedlist存储一副牌,完成洗牌功能
- ubuntu 下安装jdk 和配置java环境变量
- spring事物传播属性
- java文件(文件夹)操作
- JAVA集合框架的总结(集合嵌套)
- JAVA中的数据类型和变量
- 01_JNI是什么,为什么使用,怎么用JNI,Cygwin环境变量配置,NDK案例(使用Java调用C代码),javah命令使用
- 01_JNI是什么,为什么使用,怎么用JNI,Cygwin环境变量配置,NDK案例(使用Java调用C代码),javah命令使用
- Ubuntu 12.04 LTS 安装JDK
- java代理模式
- Java:对象的强、软、弱和虚引用
- Java Decompiler Eclipse 安装
- Windows下Eclipse 安装 android maven插件教程
- 设计模式——观察者模式(二)
- spring2.5 注解依赖注入由于jdk1.8产生的问题