网上很多技术,都没有以一种让人理解的方式讲解。今天让一下 Java Enum 枚举类
最简单的枚举类定义如下:
Test.java
1 enum Weekday { 2 MON, TUE, WED, THU, FRI, SAT, SUN; 3 }
这是个用于表示一周的枚举类,说到它是个 class 类,却让人感觉怪怪的。当 java 源代码在编译的时候,会先被改写,然后再生成 .class 文件。所以,反编译 .class 文件就能得到它被改写后的代码。
演示过程 Test.java ---> Weekday.class ---> Weekday.java
PS D:\demo> ls
Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2020/7/24 17:02 466 Test.java PS D:\demo> javac -encoding utf8 Test.java PS D:\demo> ls
Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2020/7/24 17:02 466 Test.java -a--- 2020/7/24 17:07 1370 Weekday.class PS D:\demo> jad -s java -o Weekday.class Parsing Weekday.class... Generating Weekday.java PS D:\demo>
Weekday.java 整理如下:
1 final class Weekday extends Enum { 2 3 private Weekday(String s, int i){ 4 super(s, i); 5 } 6 7 public static final Weekday MON; 8 public static final Weekday TUE; 9 public static final Weekday WED; 10 public static final Weekday THU; 11 public static final Weekday FRI; 12 public static final Weekday SAT; 13 public static final Weekday SUN; 14 private static final Weekday $VALUES[]; 15 16 static { 17 MON = new Weekday("MON", 0); 18 TUE = new Weekday("TUE", 1); 19 WED = new Weekday("WED", 2); 20 THU = new Weekday("THU", 3); 21 FRI = new Weekday("FRI", 4); 22 SAT = new Weekday("SAT", 5); 23 SUN = new Weekday("SUN", 6); 24 25 $VALUES = (new Weekday[] { 26 MON, TUE, WED, THU, FRI, SAT, SUN 27 }); 28 } 29 30 public static Weekday[] values(){ 31 32 return (Weekday[])$VALUES.clone(); 33 } 34 35 public static Weekday valueOf(String s){ 36 37 return (Weekday)Enum.valueOf(Weekday, s); 38 } 39 40 }
查得 Enum 类构造方法就两个参数,名称和索引:
1 protected Enum(String name, int ordinal) { 2 this.name = name; 3 this.ordinal = ordinal; 4 }
再看一个重写了构造方法的枚举类:
1 enum Weekday { 2 3 MON(1, "星期一"), TUE(2, "星期二"), WED(3, "星期三"), THU(4, "星期四"), FRI(5, "星期五"), SAT(6, "星期六"), SUN(0, "星期日"); 4 5 public final int number; //数字表星期 6 private final String chinese; //中文名 7 8 private Weekday(int number, String chinese) { 9 10 this.number = number; 11 this.chinese = chinese; 12 } 13 14 @Override 15 public String toString() { 16 return this.chinese; 17 } 18 19 }
反编译后的代码如下:
1 final class Weekday extends Enum { 2 3 public static final Weekday MON; 4 public static final Weekday TUE; 5 public static final Weekday WED; 6 public static final Weekday THU; 7 public static final Weekday FRI; 8 public static final Weekday SAT; 9 public static final Weekday SUN; 10 private static final Weekday $VALUES[]; 11 12 public final int number; 13 private final String chinese; 14 15 static { 16 MON = new Weekday("MON", 0, 1, "\u661F\u671F\u4E00"); 17 TUE = new Weekday("TUE", 1, 2, "\u661F\u671F\u4E8C"); 18 WED = new Weekday("WED", 2, 3, "\u661F\u671F\u4E09"); 19 THU = new Weekday("THU", 3, 4, "\u661F\u671F\u56DB"); 20 FRI = new Weekday("FRI", 4, 5, "\u661F\u671F\u4E94"); 21 SAT = new Weekday("SAT", 5, 6, "\u661F\u671F\u516D"); 22 SUN = new Weekday("SUN", 6, 0, "\u661F\u671F\u65E5"); 23 $VALUES = (new Weekday[] { MON, TUE, WED, THU, FRI, SAT, SUN }); 24 } 25 26 private Weekday(String s, int i, int j, String s1){ 27 28 super(s, i); 29 number = j; 30 chinese = s1; 31 } 32 33 public static Weekday[] values(){ 34 35 return (Weekday[])$VALUES.clone(); 36 } 37 38 public static Weekday valueOf(String s){ 39 40 return (Weekday)Enum.valueOf(Weekday, s); 41 } 42 43 public String toString(){ 44 return chinese; 45 } 46 47 }
在 Weekday 类的构造方法的参数列表中,追加两个参数。然后,内部依然调用父类的 构造方法 Enum(String name, int ordinal) ,然后就是使用了。通常是和 switch 语句一起使用。
1 class Main { 2 3 public static void main(String[] args) { 4 5 Weekday day = Weekday.SUN; 6 7 switch(day){ 8 9 case MON: 10 case TUE: 11 case WED: 12 case THU: 13 case FRI: 14 System.out.println("Today is " + day + ". Work at office!"); 15 break; 16 case SAT: 17 case SUN: 18 System.out.println("Today is " + day + ". Work at home!"); 19 break; 20 default: 21 throw new RuntimeException("cannot process " + day); 22 } 23 24 } 25 }
用法很简单,但是不免迷惑,为什么 MON、TUE 、WED 可以直接用,当你用 System.out.print(MON) 就报错,显然,就是类似于语法的东西,会被编译器改写。