枚举类
背景及定义
自定义枚举类与enmu对比
在上一篇java高级之多线程中,生命周期的线程的状态中,有这样的一段代码,分别代表线程的新建状态、运行状态、阻塞状态、等待状态、超时等待状态、终止状态。
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
那么假如现在不用枚举类或者说,在枚举类的用法还没发行之前,我们想表示线程的这几种状态时,又该怎么写呢?经过一番思考,它应该符合以下几个条件:
这些状态是有限个的,也就是说我们设计的线程状态一共有6种;
这6种状态都应该是State类的实例;
除下自己定义的这6种状态外,不应该在State类外面实例化一个状态,换句话说,状态一共就6种,并且已经在State类中实例化好了。那么该类的构造方法应该是私有private的;
状态应该是静态static的,这样可以通过类名直接调用;
状态是常量,用final修饰。
public class State {
//私有的构造方法
private State(){}
//实例化6种状态
public static final State NEW = new State();
public static final State RUNNABLE = new State();
public static final State BLOCKED = new State();
public static final State WAITING = new State();
public static final State TIMED_WAITING = new State();
public static final State TERMINATED = new State();
//想打印一下当前线程的名字
public static void printNowState(State state){
if(state == NEW)
System.out.println("NEW");
else if(state == RUNNABLE)
System.out.println("RUNNABLE");
else if(state == BLOCKED)
System.out.println("BLOCKED");
else if(state == WAITING)
System.out.println("WAITING");
else if(state == TIMED_WAITING)
System.out.println("TIMED_WAITING");
else if(state == TERMINATED)
System.out.println("TERMINATED");
}
}
class Teststate {
public static void main(String[] args) {
//新建状态
System.out.println("线程的新建状态" + State.NEW);
//打印出状态名,重写toString也打印不出来当前状态名字,因为toString方法没有参数。
State.printNowState(State.NEW);
}
}
枚举类
简单介绍
类的对象只有有限个,并且是确定的。例如:星期、季节、性别、线程状态等。
相对于自定义常量来说,枚举类更加直观,类型安全。
枚举类特点
私有化类的构造器,无法在类的外部创建对象;
枚举类的实例。声明为:public static final ;
枚举类对象的属性使用 private final 修饰,不允许被修改;
枚举类的属性应该在构造器中为其赋值;
若枚举类显式的定义了带参数的构造器, 则在列出枚举值时也必须对应的传入参数。
使用说明
枚举类使用的是enum关键字,继承自java.lang.Enum,且无法被继承;
必须在枚举类的第一行声明枚举类对象;
枚举类的所有实例必须在枚举类中显式列出,(用“,” 分隔、用“ ;” 结尾);
定义的每个实例都是引用类型的唯一实例;
只能定义出enum的实例,而无法通过new操作符创建enum的实例;
列出的实例系统会自动添加 public static final 修饰;
使用enum变量的时候,【类名.变量名】;
可以将enum类型用于switch语句。
枚举类反编译
如上使用枚举类定义线程状态时,编译器编译出的class文件类似于这样:
//该类继承自Enum,被标记为final class
public final class State extends Enum {
//每个实例均为全局唯一,均为static final修饰。
public static final State NEW = new State();
public static final State RUNNABLE = new State();
....
public static final State TERMINATED = new State();
// 构造器私有化,在类的外部无法调用new操作符。
private State() {}
}
主要方法
如上,我们定义出线程状态的枚举类后,使用枚举类State的常用方法有:
方法实战
public static void main(String[] args) {
//返回枚举类对象的名字,枚举类对象的名字不用重写toString
System.out.println(State.NEW.toString());
System.out.println("============我是分隔符=============");
//返回所有的枚举类对象构成的数组
State[] states = State.values();
for (int i = 0; i < states.length; i++) {
System.out.println(states[i]);
}
System.out.println("============我是分隔符=============");
//valueOf(String objName):返回枚举类中对象名是objName的对象。传入的objName应该存在,否则抛异常IllegalArgumentException
State state = State.valueOf("NEW");
System.out.println(state);
System.out.println("============我是分隔符=============");
//枚举的switch用法
State scase = State.BLOCKED;
switch (scase) {
case NEW:
System.out.println("我的线程状态是" + scase.toString());
break;
case RUNNABLE:
System.out.println("我的线程状态是" + scase.toString());
break;
case BLOCKED:
System.out.println("我的线程状态是" + scase.toString());
break;
case WAITING:
System.out.println("我的线程状态是" + scase.toString());
break;
case TIMED_WAITING:
System.out.println("我的线程状态是" + scase.toString());
break;
case TERMINATED:
System.out.println("我的线程状态是" + scase.toString());
break;
default:
throw new RuntimeException("查不到定义的线程状态" + scase.toString());
}
}
控制台的输出
总结
枚举类的出现是为了解决类的对象是有限个并且是确定的情况;
构造器私有化;
必须首行声明枚举类对象,逗号隔开,分号结尾。