1、枚舉類介紹
如果一個類的實例是有限且確定的,那么可以使用枚舉類。比如:季節類,只有春夏秋冬四個實例。
枚舉類使用enum進行創建,其實例必須從”第一行“開始顯示寫出。
enum Season{
SPRING,SUMMER,FALL,WINTER;//默認public static final,這都是Season類的對象。
}
特點:
1、枚舉類的對象默認都是public static final
2、枚舉類的構造器都是private,所以無法在外部創建其實例,這也決定了枚舉類實例的個數的確定性(寫了幾個就是幾個)。
3、enum類不可被繼承。

4、enum類默認extends java.lang.Enum,所以無法再繼承其他類
2、遇到的問題
enum類默認被final修飾的情況下,是無法有子類的。但是在《瘋狂Java講義》中是這么說的:
那么,問題來了:
enum Season{
// SPRING,SUMMER,FALL,WINTER;//默認public static final,這都是Season類的對象。
SPRING{
public void show(){
System.out.println("I'm Spring");
}
},SUMMER,FALL,WINTER;
private String name;
//構造器默認且只能是private
Season(){
System.out.println("Season run...");//運行四次
}
public void setName(){
//Java5開始,switch方法支持枚舉類對象。
switch(this){
case SPRING:
name="春";
break;
case SUMMER:
name="夏";
break;
case FALL:
name="秋";
break;
case WINTER:
name="冬";
break;
}
}
public void setName1(String name){
this.name=name;
}
public String getName(){
return name;
}
public void show(){
System.out.println("I'm show");
}
}
運行結果:

問題:SPRING是Season匿名子類的對象,但是前面已經說明Season類是final的?
3、真相
1、當在enum類中創建匿名子類對象的時候,在運行時,會將Season編譯為一個.class文件,沒有final修飾:

同時對於匿名子類,會生成一個.class文件:

2、當enum類中沒有匿名子類對象時,對應的class就是final的:

3、如果enum類中含有抽象方法,那么這個類就是抽象的:給出的對象必須實現抽象方法:


即便如此,還是無法繼承該類:

可以看出,即便enum中有抽象方法,它也是被final修飾的,由於final 和abstract是不能同時出現的。所以我認為:枚舉類實際上不存在final、abstract。只是規定不能被繼承,final、abstract是對於運行時生成的對應class而言的。
結論:
1、enum類不存在final或者abstract的,就是不能被繼承。如果像《瘋狂Java講義》中說的,非抽象枚舉類默認是final的,那么應該可以顯示用final修飾,但是不行:


所以說,enum本身不存在final、abstract的說法。就是不能被繼承。運行時生成的class才有final、abstract的說法。
2、運行時,會生成對應的.class文件(可以理解為一個新的class類型的類)。
2.1、如果enum類中沒有抽象方法,也沒有匿名子類對象,那么這個類是被final修飾的。
2.2、如果enum類中有抽象方法,那么這個類是抽象的,對象必須實現該抽象方法。
2.3、如果enum類中沒有抽象方法,但是有匿名子類對象,那么這個類不被final修飾,也不是抽象的。
