昨天在做besuper的小型交互游戏的时候,强默默走到我边上,然后看了一眼我的代码,又一如既往的开始喷我:你这写的啥玩意儿啊!这么多类常量定义在前面,干嘛创建一个枚举类型!也就是因为这样被喷的经历,让我今天下决心好好了解一下enum的用法。
优势
为什么在有些时候我们要用枚举呢?所以先看看枚举常量和我们经常使用的类常量、实例常量比较,有什么优势。
- 枚举常量更加简单
在接口中定义类常量,如下:
interface Season {
int Spring = 0;
int Summer = 1;
int Autumn = 2;
int Winter = 3;
}
在枚举中定义常量
public enum Season {
SPRING, SUMMER, AUTUMN, WINTER;
}
枚举只需要定义每一个枚举项(其实每个枚举项就是一个枚举类型的实例对象),不需要定义枚举值,而接口常量(即类常量)则必须初始化,否则编译不通过。两个引用方式相同(类名.属性),但是枚举表示的是一个枚举项,字面量就是SPRING、SUMMER、AUTUMN、WINTER,而接口常量字面量是一个int类型:0、1、2、3。
- 枚举常量属于稳定型
如果我们使用一个接口常量,我们就必须要对输入值进行检查,确定是否越界,如果常量非常庞大,校验输入就是一件非常麻烦的事情,但是这个过程又无法避免。
public void describe(int s) {
if (s >= 0 && s <= 4) {
switch(s) {
case Season.Summer:
System.out.println("Summer is very hot!");
break;
case Season.Winter:
System.out.println("Winter is very cold!");
break;
}
}
}
如果是枚举常量,我们看看它是怎么避开校验的。
public void describe(Season s) {
switch(s) {
case Season.Summer:
System.out.println("Summer is very hot!");
break;
case Season.Winter:
System.out.println("Winter is very cold!");
break;
}
}
因为我们已经限定了输入的参数只能是Season枚举,所以只能输入Season的四个实例。这也是枚举很好的一个作用:在编译期间限定类型,不允许发生越界的情况。
- 枚举具有内置方法
每个枚举都是java.lang.Enum的子类。该基类提供了很多方法:获得排序值得ordinal(),compareTo()等。比如列出所有的枚举值:
public static void main(String[] args) {
for (Season s : Season.value()) {
System.out.println(s);
}
}
- 枚举可以自定义方法
这一点看上去不是枚举的优点,因为在定义类常量所在的类里面也可以定义方法,但是枚举在可以定义静态方法和实例方法的基础之上,还可以从根本上杜绝枚举常量在别的类中被实例化(因为枚举的构造方法默认是private的,所以只允许在枚举中实例化,不允许在别的地方进行实例化。这也是枚举的意义之一!)。
枚举实现:
enum Season {
SPRING, SUMMER, AUTUMN, WINTER;
public static Season getComfortableSeason() {
return SPRING;
}
}
类实现:
class Season {
public final static int Spring = 0;
public final static int Summer = 1;
public final static int Autumn = 2;
public final static int Winter = 3;
public static void int getComfortableSeason() {
return Spring;
}
}
- 虽然枚举在很多方面都比接口常量和类常量做得好,但是有一点它比不上接口常量和类常量,就是继承。因为枚举是不能被继承的,也就是说一个枚举常量定义之后,除非修改重构,否则无法做扩展。但是,我们依旧要用枚举常量替代接口常量或者类常量。
枚举常量一个很关键的用法
先定义一个枚举类
enum Season {
SPRING, SUMMER, AUTUMN, WINTER;
}
}
再定义一个类
public class chooseSeason {
String s = "spring";
Season season = Season.valueOf(s.toUpperCase());
switch (season) {
case SPRING :
System.out.println("这是春天");
case SUMMER:
System.out.println("这是夏天");
case AUTUMN:
System.out.println("这是秋天");
case WINTER:
System.out.println("这是冬天");
}
}
这里,我们是想把一个常量传入switch,然后进行一个选择。这里我们运用了枚举的第一个特点,就是switch()里面的参数类型定死为Season枚举类型了。但是,如果我们得到的数据是一个字符串,我们想把这个字符串的字面量当做switch的条件传入怎么办呢?这个时候,我们把字符串变成大写,并通过Enum里面的valueOf()方法,把字符串转成枚举常量。并且这个枚举常量的字面量就是原来字符串的字面量。
这样的转换在switch里面真的好用
网友评论