Java Enum的多态性
转载自:http://pf-miles.iteye.com/blog/187155
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 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的多态性的更多相关文章
- java enum
小谈Java Enum的多态性 博客分类: Java JavaAppleJDKJVMIDEA Enum+多态,我没说错,不过Enum是不可以被继承的,也不可以继承自别人,只是能实现接口而已,何谈多态 ...
- Java Enum用法详解
Java Enum用法详解 用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举 ...
- 如何使用Java Enum
简单的用法:JavaEnum简单的用法一般用于代表一组常用常量,可用来代表一类相同类型的常量值.如: 性别: public enum SexEnum { male, female; } 颜色: pub ...
- 将子类对象引用赋值给超类对象 JAVA 编译时多态性
将子类对象引用赋值给超类对象 JAVA 编译时多态性(转) (2012-05-10 11:24:05) 转载▼ 标签: 杂谈 分类: 也无晴_soft 1.通过将子类对象引用赋值给超类对象引用变量来实 ...
- (转)java enum枚举
转载自: 原理:http://singleant.iteye.com/blog/686349 应用:http://www.cnblogs.com/happyPawpaw/archive/2013/04 ...
- java enum naming rules & Pascal case, Camel case, Uppercase
java enum naming rules Constant & all Capital Case https://stackoverflow.com/questions/3069743/c ...
- The Java Enum: A Singleton Pattern [reproduced]
The singleton pattern restricts the instantiation of a class to one object. In Java, to enforce this ...
- 【转】Java enum的用法详解
用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. p ...
- Java enum的用法详解[转]
Ref:http://www.cnblogs.com/happyPawpaw/archive/2013/04/09/3009553.html 用法一:常量 在JDK1.5 之前,我们定义常量都是: p ...
随机推荐
- POJ 2318 TOYS | 二分+判断点在多边形内
题意: 给一个矩形的区域(左上角为(x1,y1) 右下角为(x2,y2)),给出n对(u,v)表示(u,y1) 和 (v,y2)构成线段将矩形切割 这样构成了n+1个多边形,再给出m个点,问每个多边形 ...
- 商店购物 (shopping.c/cpp/pas)
1.商店购物 (shopping.c/cpp/pas) 在滨海市开着 n 家商店,编号依次为 1 到 n,其中编号为 1 到 m 的商店有日消费量上 限,第 i 家商店的日消费量上限为 wi. 海霸王 ...
- 威士忌(whiskey)
威士忌(whiskey) 题目描述 Alan 喝了假威士忌,想问你一个问题: nvliu66 推荐大家读三本书<百年孤独>.<城市发展史>.<美国大城市的生与死>, ...
- Nodejs 基础知识 浅析
1. 模块化 ①常用模块化规范 CommonJS + nodejs AMD(Asynchronous Module Definition) + RequireJS CMD(Common Module ...
- 转:Java SoftReference 使用构建对象缓存
本文介绍对象的强.软.弱和虚引用的概念.应用及其在UML中的表示. 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说, ...
- 学习C++ -> 向量(vector)
一.向量的介绍 向量 vector 是一种对象实体, 能够容纳许多其他类型相同的元素, 因此又被称为容器. 与string相同, vector 同属于STL(Standard Template Lib ...
- 各版本Sql Server下载地址全
SQL Server 2014简体中文企业版 文件名:cn_sql_server_2014_enterprise_edition 32位下载地址:ed2k://|file|cn_sql_server_ ...
- [ CodeVS冲杯之路 ] P3116
不充钱,你怎么AC? 题目:http://codevs.cn/problem/3116/ 基础的高精度加法,注意一下两个数长短不一和答案第一位的处理即可,当然也可以用压位的方法做 #include&l ...
- vue实现tab切换
需要弄类似tab切换的功能就是一个点击切换上一页下一页的页面 找到这个获得灵感 <!DOCTYPE html> <html lang="en"> <h ...
- 厌倦了ListBox打印消息,使用RichTextBox试试吧
背景 Winform打印后台线程运行时消息,习惯用ListBox,有时候某行消息过长,设置个Tooltip控件提示全部信息.后来无意中看到同事使用RichTextBox打印消息,然后在不同的消息类别上 ...