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是一种广泛使用的面向对象编程语言,其面向对象的特性之一就是多态性。多态性是面向对象编程的重要概念,它允许我们使用一个接口来表示多种类型的数据,从而增加了代码的灵活性和可重用性。在Java中,多态性的...
枚举是一种特殊的类,它可以拥有方法和属性,同时它还具备了类的多态性。枚举的定义通常如下: ```java public enum Color { RED, GREEN, BLUE; } ``` 在这里,`Color`是一个枚举类,包含三个预定义的实例:`RED`...
此外,枚举可以实现接口,从而实现多态性。 ```java interface Shape { void draw(); } enum Shapes implements Shape { CIRCLE { @Override public void draw() { System.out.println("Drawing a circle...
枚举可以实现一个或多个接口,从而实现多态性。这使得枚举类可以拥有特定的行为。 7. **枚举常量的顺序**: 枚举常量的顺序与它们在枚举类中声明的顺序相同,可以用来进行比较操作,例如使用 `compareTo()` 方法...
枚举类型的实例可以被视为对象,因此可以作为参数传递给接受父类型参数的方法,实现多态性。例如,如果有一个`Shape`接口,我们可以定义一个`ShapeType`枚举,并在方法签名中使用`Shape`作为参数: ```java public ...
- 枚举可以继承其他类或实现接口,从而实现多态性,增加枚举的灵活性。 - 通过抽象枚举类,可以定义一些共有的方法或属性,供子类枚举实例共享。 5. **枚举与工具类的结合**: - 枚举工具类:有时,我们可能会...
枚举可以作为方法参数或返回值类型,支持多态性。例如,定义一个接受任何枚举类型的方法: ```java public void handle(Enum<?> e) { ... } ``` 10. 枚举枚举: Java允许枚举类型中包含其他枚举类型的枚举常量...
Java 提供了多种方式来使用多态性,包括使用继承、接口和抽象类等。 在 Java 中,抽象类是指一个不能被实例化的类,它只能被继承。抽象类可以提供公共的方法和变量,供子类继承和使用。Java 提供了多种方式来使用...
Java中的多态性主要体现在方法重写和接口实现上。 5. 构造器:构造器是类的一个特殊方法,用于初始化新创建的对象。Java中的构造器与类名相同,没有返回类型。 6. 抽象类与接口:抽象类不能被实例化,但可以有子类...
这体现了面向对象的继承特性,同时,`Fan`类还可以覆盖或扩展基类的方法,展示多态性。 3. **接口**:如果风扇有多个档位,可以定义一个`SpeedLevel`接口,定义不同速度级别。`Fan`类可以实现这个接口,并提供对应...
Java中的枚举类型是编程语言特性的一个重要组成部分,它提供了类型安全、紧凑...它解决了早期版本中缺乏枚举类型的问题,同时也适应了多态性和面向对象编程的需求,为开发者提供了更丰富的工具来编写高效、可靠的代码。
4. 多态性(Polymorphism):多态性意味着同一种行为可以有多种不同的表现形式。在Java中,这通常通过方法重载(相同方法名但参数列表不同)和方法覆盖(子类重写父类的方法)来实现。 5. 接口(Interface):接口...
Java 是一种广泛使用的面向对象的编程语言,其核心特性包括抽象、继承、封装和多态性。这些特性构成了Java设计的基础。 1. 抽象:抽象是面向对象编程的关键概念,它允许我们将现实世界的复杂性简化为一系列类。数据...
这篇笔记将深入探讨Java中的面向对象概念,包括类、对象、封装、继承和多态性。 首先,我们要理解什么是面向对象。面向对象编程(Object-Oriented Programming, OOP)是一种编程范式,它以对象为中心,通过对象来...
你可以看到如何定义类、创建对象,以及如何通过继承和接口实现多态性。 3. **异常处理**:Java的异常处理机制是程序健壮性的保障,源码中包含了try-catch-finally结构的实例,展示了如何捕获和处理运行时错误。 4....
3. 多态:多态性是面向对象的重要特性,它允许不同的对象对同一消息作出不同的响应。Java通过方法重写(Override)和方法重载(Overload)来实现多态。 4. 接口:接口在Java中是一种完全抽象的类,它只包含常量和...
8. **多态和继承**:Java是面向对象的语言,支持多态性(Polymorphism)和继承(Inheritance),这使得代码更加模块化和可重用。 9. **枚举(Enum)**:Java 5引入的枚举类型,用于定义一组相关的常量,提高了代码...
4. **多态性**:多态性是指同一消息可以被不同类型的对象响应,它是面向对象的三大特性之一。Java中的多态主要通过方法重载(overloading)和方法重写(overriding)实现。 5. **异常处理**:Java提供了强大的异常...
这包括如何定义和调用方法,使用数据类型,以及类的继承和多态性。 2. **Swing或JavaFX库**:在本项目中,游戏界面是通过Swing或JavaFX库构建的。Swing是Java的标准GUI工具包,提供了丰富的组件,如JFrame(窗口)...
Java通过接口和抽象类支持多态性。例如,我们可以定义一个`Animal`接口,包含`sound()`方法,然后让`Dog`和`Cat`类实现这个接口,各自给出不同的`sound()`实现。 ```java interface Animal { void sound(); } ...