Java 枚举详细解读及用法
定义
枚举是Java 1.5版本引入的新特性,Java 创建枚举类型要使用 enum 关键字,并且所创建的类型都是 java.lang.Enum 类的子类。枚举类是一种特殊类,它和普通类一样可以使用构造器、定义成员变量和方法,也能实现一个或多个接口,但枚举类不能继承其他类.
注意:既然枚举都是Enum的子类,所以也要看一下Enum有哪些特性;
Enum源码:
public abstract class Enum implements Comparable, Serializable {}
从源码可以看出Enum实现了Comparable接口和Serializable接口,所以枚举是可以比较排序的(与TreeSet配合排序)和可序列化的特性;
语法
使用关键字enum使用以下语法定义枚举类型:
enum {
enum-body,
}
与类的访问修饰符相同:public,private,protected或package-level。
enum-body 枚举项,或者叫枚举成员,多个枚举成员之间使用逗号分隔。注意:枚举项一定要在第一行不然不报错;
主要用途及
1,单例
public enum Year {
Y2021
}
注意:如果定义多个枚举项,就是不是单例,就成多例了(多例就是实例的个数是有限个,一般十个以内比较好,其实枚举就是多例;但枚举项只有一个的时候就是单例);
2,常量
在枚举类型中定义的常量(枚举项)是该枚举类型的实例。
public enum Week {
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}
public void run(Week week) {
if (week.equals(Week.Monday)) {
System.out.println("周一跑步");
}
if (week.equals(Week.Tuesday)) {
System.out.println("周二瑜伽");
}
if (week.equals(Week.Wednesday)) {
System.out.println("周三打篮球");
}
if (week.equals(Week.Thursday)) {
System.out.println("周四打羽毛球");
}
}
3,在switch语句中使用
private void run(Week week) {
switch (week) {
case Monday:
System.out.println("周一跑步");
break;
case Tuesday:
System.out.println("周二瑜伽");
break;
case Wednesday:
System.out.println("周三打篮球");
break;
default:
break;
}
}
public enum Week {
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}
4,枚举中可以有抽象方法
还可以在枚举类中给出抽象方法,然后在创建每个枚举项时使用“特殊”的语法来重复抽象方法。所谓“特殊”语法就是匿名内部类!也就是说每个枚举项都是一个匿名类的子类对象!
public enum Color{
RED{
@Override
public void test() {
System.out.println("RED 重写了test方法");
}
},
BLUE{
@Override
public void test() {
System.out.println("BLUE 重写了test方法");
}
};
public abstract void test();
}
}
5,构造方法
枚举的构造方法默认是private修饰的;
6,枚举中可以有方法和变量
public enum Week {
Monday("周一"), Tuesday("周二"), Wednesday("周三"), Thursday("周四"), Friday("周五"), Saturday("周六"), Sunday("周日");
private String name;
Week(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
7,可以实现接口
接口
interface Command {
void execute();
}
实现接口的枚举
class enum Level implements Command {
LOW {
public void execute() {
System.out.println("Low...");
}
},
HIGH {
public void execute() {
System.out.println("HIGH...");
}
};
public abstract void execute();
}
}
8,使用接口组织枚举
public interface Food {
enum Coffee implements Food{
BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO
}
enum Dessert implements Food{
FRUIT, CAKE, GELATO
}
}
9,常用方法
values():返回本类所有枚举常量;
valueOf(String name):通过枚举常量的名字返回枚举常量,注意,这个方法与Enum类中的valueOf()方法的参数个数不同。
枚举类的特点总结
1,枚举实例必须在 enum关键字声明的类中显式的指定(首行开始的以第一个分号结束)
2,除了1, 没有任何方式(new,clone,反射,序列化)可以手动创建枚举实例
3,枚举类不可被继承
4,枚举类是线程安全的
5,枚举类型是类型安全的(typesafe)
6,无法继承其他类(已经默认继承Enum)
总结
如果还是不能理解枚举的一些特性及使用的话,可以通过反编译看一下原码,然后很多疑惑迎刃而解;
例如枚举类
public enum Color {
RED, BLUE,GREEN;
}
反编译之后得到的编译后的原码如下,然后在对应着枚举之父类Enum的原码去理解,更容易学习和记忆;如果想查看反编译的可以参考这边文章手把手教你怎么通过字节码生成编译的Java原码
public final class Color extends Enum
{
public static Color[] values()
{
return (Color[])$VALUES.clone();
}
public static Color valueOf(String name)
{
return (Color)Enum.valueOf(com/company/Color, name);
}
private Color(String s, int i)
{
super(s, i);
}
public static final Color RED;
public static final Color BLUE;
public static final Color GREEN;
private static final Color $VALUES[];
static
{
RED = new Color("RED", 0);
BLUE = new Color("BLUE", 1);
GREEN = new Color("GREEN", 2);
$VALUES = (new Color[] {
RED, BLUE, GREEN
});
}
}