Java面试_枚举类型
一、Java 5 之前定义"枚举类型"
Java 5之前是没有枚举类型的,在Java 5之前程序员们使用以下方式来解决与枚举类似的问题:
//定义‘枚举’类
class NUM{
private NUM(){} //私有化构造器
private static final NUM ONE = new NUM();
private static final NUM TWO = new NUM();
private static final NUM THREE = new NUM();
private static final NUM FORE = new NUM();
//方法
...
}
//调用
public class Test{
public static void main(String[] args){
NUM choose = NUM.ONE;
//if(choose == new NUM()){ //私有化构造器为了防止这样的非法创建
if(choose == NUM.ONE){
System.out.println("NUM1");
}else{
System.out.println("NOT NUM1");
}
}
}
- 在上面方法中使用私有化构造器是为了保护该枚举类,不让其他程序自己去使用 new 创建一个该类的对象。
- 使用static 的 final的常量来做为成员,并为public 可由外部直接通过类名直接访问。
- 因为所有的枚举都是常量,所以尽量使用大写来表示枚举类型。
二、Java 5之后的枚举类型
enum NUM{
ONE,TWO,THREE,FORE; //只可以写在枚举体的最开始的部分
private NUM(){}; //构造器可以省略,如果写的话,必须为私有private
//方法
...
}
在底层,类似于上面 java 5之前 NUM类的实现,不过枚举自身带有许多的方法。
- enum类型直接继承 java.lang.Enum 类,但是不能显式继承(即不能写成 enum NUM extends java.lang.Enum)。
- enum 相当于一个类,可以有自己的构造器,成员变量,普通方法和抽象方法。
- 默认为私有的构造方法,不可以改变。
- 枚举实例必须位于枚举体最开始的部分,每个实例用‘,’分隔,最后使用‘;’与其他成员分隔。
三、 java.lang.Enum类原码分析
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
//以下成员为 final 不可被重写覆盖的
//===========================================
//枚举常量名
private final String name;
public final String name() {
return name;
}
//枚举常量的下标
private final int ordinal;
public final int ordinal() {
return ordinal;
}
//构造函数
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
// toString 方法,返回枚举常量名
public String toString() {
return name;
}
//equlse方法 ,直接比较两个枚举对象的地址,即比较两个枚举对象
public final boolean equals(Object other) {
return this==other;
}
/**
* enum classes cannot have finalize methods. 不可以有finalize方法
*/
protected final void finalize() { }
...
}
枚举相当于使用java.lang.Enum ,并在自身创建了很多自己的对象(结合上面的 一 和 二),它自己本身是个类,可以有自己的方法,成员等等。
【参考博客】https://blog.csdn.net/guohengcook/article/details/81277070
三、switch-case 与 枚举
1. switch-case
枚举只可以识别 int 类型,所支持的所有类型都是最终转化为 int
在java 5 之前
- 只支持 byte,shot,char,int 基本数据类型。
在java 5之后
- 由于自动拆箱的缘故,也支持上面四种基本类型的包装类。
- 支持枚举类型。
在java 7 之后
- 支持String类型,并使用HashCode去比较,又由于两个String的HashCode可能相同,在编译时,JVM会自动加上使用equlse再进行比较。
2. switch-case与枚举
枚举使用switch-case时,在编译时,会将枚举常量使用 ordinal() 方法转化为 int ,比较的是下标序号。
四、 枚举练习
1.枚举中的方法
public class TestEnum {
public static void main(String[] args) {
NUM[] nums = NUM.values();
for (NUM num : nums) {
System.out.println(num.ordinal() + " " + num.name() + " " + num);
}
}
}
enum NUM{
ZERO("零"), ONE("壹"),TWO("贰");
private final String name;
NUM(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
运行结果
0 ZERO 零
1 ONE 壹
2 TWO 贰
2.枚举实现接口
枚举实例后带花括号,表示 其为匿名内部类对象。
测试1:
public class TestEnum {
public static void main(String[] args) {
NUM[] nums = NUM.values();
for (NUM num : nums) {
System.out.println(num.fun());
}
}
}
interface Interface {
public String fun();
}
enum NUM implements Interface{
ZERO, ONE,TWO;
@Override
public String fun() {
return "Enum.NUM";
}
}
运行结果:
Enum.NUM
Enum.NUM
Enum.NUM
测试2
public class TestEnum {
public static void main(String[] args) {
NUM[] nums = NUM.values();
for (NUM num : nums) {
System.out.println(num.fun());
}
}
}
interface Interface {
public String fun();
}
enum NUM implements Interface {
ZERO {
@Override
public String fun() {
return "ZERO";
}
},
ONE {
@Override
public String fun() {
return "ONE";
}
},
TWO {
@Override
public String fun() {
return "TWO";
}
};
}
运行结果:
ZERO
ONE
TWO