思维导图
点击标题可下载xmind文件
代码练习
import java.util.Arrays;
public class EnumTest {
public static void main(String[] args) {
System.out.println(Season.SPRING);
// 枚举类默认继承java.lang.Enum,可以继承父类的实例方法toString(),name(),values(),valueOf(),compareTo(),ordinary()
System.out.println(Season.SPRING.toString());
System.out.println(Season.SPRING.name());
System.out.println(Arrays.toString(Season.values()));
System.out.println(Season.valueOf("SPRING"));
System.out.println(Season.SPRING.compareTo(Season.FALL));
System.out.println(Season.SPRING.ordinal());
// 测试枚举类的get方法
System.out.println(Season.SPRING.getId()+"-"+Season.SPRING.getDesc());
// 测试枚举类,及实例实现的抽象方法
Season.SPRING.info();
Season.SUMMER.info();
Season.SPRING.test();
// switch判断的参数可以传入byte,short,char,int,String,枚举类类型数据
switch(Season.SPRING){
case WINTER:
System.out.println("switch winter");
break;
case SUMMER:
System.out.println("switch summer");
break;
case FALL:
System.out.println("switch fall");
break;
case SPRING:
System.out.println("switch spring");
break;
default:
System.out.println("输入非合法季节");
}
}
}
// 使用enum关键字定义的枚举类,默认继承java.lang.Enum类
// 枚举类实现接口
// 枚举类包含抽象方法,系统会隐式加abstract修饰,但不能显式加abstract
enum Season implements Info{
// 枚举类实例必须定义在枚举类定义中第一行,实例间以逗号隔开,以分号结束。
// 枚举类实例其实是实例名, 类似于 Season SPRING = new Season();
// 枚举类实例默认使用public static final修饰,即public static final SeaSon SPRING = new Season();
// 枚举类实例后面是否跟参数,取决与构造器定义
SPRING(1,"春"){
@Override
public void test() {
System.out.println("测试春天");
}
},
// 枚举类实现接口,也可以基于枚举类实例来重写接口抽象方法
// 枚举类包含抽象方法,只能基于枚举类实例来重写抽象方法
/**
* 基于枚举类实例重写抽象方法,其实是定义枚举类的匿名内部类,即枚举类的子类实例
* public static final SUMMER = new Season(){
* 重写抽象方法
* }
*/
SUMMER(2,"夏"){
@Override
public void info() {
System.out.println("这是夏天");
}
@Override
public void test() {
System.out.println("测试夏天");
}
},
FALL(3,"秋"){
@Override
public void info() {
System.out.println("这是秋天");
}
@Override
public void test() {
System.out.println("测试秋天");
}
},
WINTER(4,"冬"){
@Override
public void info() {
System.out.println("这是冬天");
}
@Override
public void test() {
System.out.println("测试冬天");
}
};
// 枚举类的成员变量建议使用private final修饰
private final int id;
private final String desc;
// 枚举类的构造器只能使用private修饰,private可以省略
private Season(int id,String desc){
this.id = id;
this.desc = desc;
}
// 枚举类只提供get方法,不提供set方法
public int getId(){
return id;
}
public String getDesc(){
return desc;
}
// 枚举类实现接口可以基于类来实现接口的抽象方法
public void info(){
System.out.println("这是季节枚举类");
}
// 枚举类包含抽象方法
public abstract void test();
}
interface Info{
void info();
}
思考题
1.枚举类是否可以派生子类?
需要分情况讨论
①抽象枚举类可以派生子类
②非抽象枚举类不可以派生子类
具体枚举类啥时候是抽象的,啥时候是非抽象的请看3
2.枚举类的构造器是私有的,那么枚举类如何派生子类? 我们知道子类的构造器最终(子类构造器重载时,总会有一个构造器第一行或隐式调用父类构造器)都会调用父类构造器,但是子类不能访问父类私有成员,而枚举类的构造器是私有。
注意只有抽象枚举类可以派生子类,非抽象枚举类不能派生子类。
我们还需要知道枚举类第一行必须定义该枚举类的实例。
对于抽象枚举类,如定义抽象方法的枚举类
enum Season{
SPING{
public void test(){
System.out.println("spring");
}
},
SUMMER{
public void test(){
System.out.println("summer");
}
},
FALL{
public void test(){
System.out.println("fall");
}
},
WINTER{
public void test(){
System.out.println("winter");
}
};
public abstract void test();
}
其中实例SPRING实际上是:
public static final Season SPRING = new Season(){
public void test(){
System.out.println("spring");
}
};
可以看出抽象枚举类的第一行定义的实例,其实是当前枚举类的子类实例(匿名内部类)
所以这个问题的最终答案是:只有抽象枚举类可以派生子类,且只能在本类中以匿名内部类的方式派生子类,并生成实例。
且可以从抽象枚举类编译后生成的字节码文件看出
Season.class,Season$1.class,Season$2.class,Season$3.class,Season$4.class
我们知道匿名内部类编译后就是【外部类名$N.class,其中N是数字】形式
3.如何定义抽象枚举类?直接在定义abstract enum 枚举类名 会怎么样?
定义抽象枚举类不能直接加abstract修饰。会编译报错。
抽象枚举类是指
①实现了接口,但是枚举类没有基于类重写该接口的所有抽象方法
②枚举类中定义了抽象方法
此时枚举类会自动隐式地被abstract修饰
非抽象枚举类是指
没有实现接口或者没有在枚举类中定义抽象方法,非抽象枚举类不能派生子类,自动隐式被final修饰
4.使用enum关键字定义的枚举类为什么不能继承父类?
因为使用enum关键字定义枚举类会自动继承java.lang.Enum类
5.枚举类定义中第一行是该枚举类的实例,那么这些显式定义的实例具体是什么?例如enum Season{SPRING,SUMMER,FALL,WINTER;}中SPING是Season的实例,那么SPRING具体是实例的什么?
SPING是实例名字,具体请看2