在编写Java程序时经常会用到枚举(后面统一用enum描述)类型,今天我们就来看一下enum中常用到的values()方法。
首先,我们在Eclipse中编写一个简单的类:
public class EnumTest {
private enum Directions {
NORTH, SOUTH, EAST, WEST
}
}
在这里,我们定义了一个名叫Directions的enum,它其中包含了四个方向。
接下来,我们写一个简单的main函数,仅仅是调用values()方法:
public static void main(String[] args) {
Directions.values();
}
在Eclipse中,我们点击某个函数、变量时,会跳转到其相应的源码位置。在此处我们尝试点击values()方法,却是没有反应的,这是为什么呢?
此外,我们在定义Directions这个enum类型时,使用的是enum这个java关键字,那么这里又是如何调用到values()方法的?
为此,我们需要了解一下enum关键字背后是如何实现的。
最直接的方法就是查阅JDK的文档了,oracle在线文档的地址在这里:
http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
篇幅不是很长,其中恰好有两段说明可以解释我们的两个问题:
The enum declaration defines a class (called an enum type). The enum class body can include methods and other fields. The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared.
首先,enum声明实际上定义了一个类。因此我们可以通过定义的enum调用其方法。其次,Java编译器会自动在enum类型中插入一些方法,其中就包括values()——所以我们的程序在没编译的时候,自然没法查看values()方法的源码了。
那么这个enum是一个什么类呢?接下来还有这样一段说明:
All enums implicitly extend java.lang.Enum. Because a class can only extend one parent (see Declaring Classes), the Java language does not support multiple inheritance of state (see Multiple Inheritance of State, Implementation, and Type), and therefore an enum cannot extend anything else.
原来,这个枚举实际上是由java.lang.Enum这个类实现的,在程序中定义的枚举类型,都会隐式继承此类。并且,由于java中的继承是单继承,所以我们定义的枚举就无法在继承其他类了。
我们来验证一下上面所说的内容:
首先在刚才的测试类(在此取名EnumTest)开头添加一行import:
import java.lang.Enum;
使用 Ctrl+左键 点击查看其源码,原来是这样一个类:
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
......
}
查看这个类的实现,果然是没有values()方法的。
接下来我们通过命令行进入到EnumTest.java文件所在目录,在此使用javac命令编译这个文件:
javac EnumTest.java
通过ls命令查看编译成功后目录中的文件,结果如下:
EnumTest$Directions.class
EnumTest.class
EnumTest.java
我们可以看到编译器已经为我们生成了EnumTest$Directions.class这样一个class文件。
通过javap命令,反编译EnumTest$Directions.class查看其中的内容:
javap EnumTest\$Directions.class
结果是这样的:
Compiled from "EnumTest.java"
final class EnumTest$Directions extends java.lang.Enum<EnumTest$Directions> {
public static final EnumTest$Directions NORTH;
public static final EnumTest$Directions SOUTH;
public static final EnumTest$Directions EAST;
public static final EnumTest$Directions WEST;
public static EnumTest$Directions[] values(); //编译器插入的方法
public static EnumTest$Directions valueOf(java.lang.String);
static {};
}
我们可以看到编译器已经自动为我们插入了values()方法了。
最后总结一下:
1.java中的enum关键字背后实际是Enum这个类实现的。
2.在我们编写自定义的enum时,其中是不含values方法的,再编译java文件时,java编译器会自动帮助我们生成这个方法。