清原招聘网站建设,centos 7安装wordpress,太原网站建设解决方案,258网站建设十六、枚举16.1 背景16.2 枚举类型16.3 EnumSet 和 EnumMap01、EnumSet02、EnumMap16.1 背景
在 Java 语言中还没有引入枚举类型之前#xff0c;表示枚举类型的常用模式是声明一组 int 类型的常量#xff0c;常常用的就是#xff1a;
public static final int SPRING 1;
…
十六、枚举16.1 背景16.2 枚举类型16.3 EnumSet 和 EnumMap01、EnumSet02、EnumMap16.1 背景
在 Java 语言中还没有引入枚举类型之前表示枚举类型的常用模式是声明一组 int 类型的常量常常用的就是
public static final int SPRING 1;
public static final int SUMMER 2;
public static final int AUTUMN 3;
public static final int WINTER 4;看似这样写是没有问题的但是我们写代码的时候通常都会考虑到它的安全性、易用性和可读性。
首先是安全性。显然这种模式并不是安全的。就拿上面的例子来说我们根本无法保证传入值的合法性在编译期和运行期不知道可能会出现什么情况这就不符合 Java 程序的类型安全了。
其次是可读性。使用枚举类型的大多数场合都是为了方便得到枚举类型的描述也就是字符串表达式如果我们只是单一的打印出来这一组数字也没有太大的用处。这时如果使用 String 来替代 int 作为常量也不是不可以的但是可能会导致性能问题因为它依赖于字符串的比较操作。
从类型安全和程序可读性两方面考虑int 和 String 枚举模式的缺点就暴露出来了。这时就引入了一个新的解决方案就是枚举类型enum type。
16.2 枚举类型
枚举enum是 Java 1.5 时引入的关键字它标识一种特殊类型的类继承自 java.lang.Enum由一组固定的常量组成合法的类型。
新建一个枚举类 Season.java
/*** 季节枚举类** author qiaohaojie* date 2023/3/22 14:07*/
public enum Season {SPRING(1),SUMMER(2),AUTUMN(3),WINTER(4);private int code;Season(int code) {this.code code;}public int getCode() {return code;}
}其实在这个类中我们并没有看到有继承关系的来扒一下反编译后的字节码
public final class Season extends Enum
{public static Season [] values(){return (Season [])$VALUES.clone();}public static Season valueOf(String name){return (Season )Enum.valueOf(com/qhj/enumtype/Season, name);}private Season(String s, int i){super(s, i);}public static final int SPRING;public static final int SUMMER;public static final int AUTUMN;public static final int WINTER;private static final Season $VALUES[];static {SPRING new Season (SPRING, 0);SUMMER new Season (SUMMER, 1);AUTUMN new Season (AUTUMN, 2);WINTER new Season (WINTER, 3);$VALUES (new Season[] {SPRING, SUMMER, AUTUMN, WINTER});}
}Java 编译器帮我们做了很多隐式的工作
要继承 Enum 类要写构造方法要声明静态变量和数组要用 static 块来初始化静态变量和数组要提供静态方法比如 values() 和 valueOf(String name)。
作为开发者我们的代码量减少了枚举看起来简洁明了。
既然枚举是一种特殊的类那么它其实是可以定义在一个类的内部的这样它的作用域就可以限定于这个外部类中使用
/*** 枚举定义在外部类中** author qiaohaojie* date 2023/3/22 22:28*/
public class SeasonClass {private Season season;public enum Season {SPRING(1),SUMMER(2),AUTUMN(3),WINTER(4);private int code;Season(int code) {this.code code;}public int getCode() {return code;}}public boolean isSeason() {return getSeason() Season.AUTUMN;}public Season getSeason() {return season;}public void setSeason(Season season) {this.season season;}
}Season 就相当于 SeasonClass 的内部类。
由于枚举是 final 的所以可以确保在 Java 虚拟机中仅有一个常量对象基于这个原因我们可以使用 “” 运算符来比较两个枚举是否相等比如上面的 isSeason() 方法。
至于为什么不用 equals() 方法呢 首先“” 运算符比较的时候如果两个对象都为 null并不会发生 NullPointerException而 equals() 方法就会发生。 另外“” 运算符会在编译时进行检查如果两侧的类型不匹配就会提示错误而 equals() 方法则不会
另外枚举还可以用于 switch 语句和基本数据类型的用法一致
public static String getChineseSeason(Season season) {StringBuffer result new StringBuffer();switch (season) {case SPRING:result.append([中文春天枚举常量 season.name() 数据 season.getCode() ]);break;case SUMMER:result.append([中文夏天枚举常量 season.name() 数据 season.getCode() ]);break;case AUTUMN:result.append([中文秋天枚举常量 season.name() 数据 season.getCode() ]);break;case WINTER:result.append([中文冬天枚举常量 season.name() 数据 season.getCode() ]);break;}如果枚举中需要包含更多信息的话可以为其添加一些字段比如code、name 等这时就需要为枚举添加一个带参的构造方法这样就可以在定义枚举时添加对应的名称了。
16.3 EnumSet 和 EnumMap
01、EnumSet
EnumSet 是一个专门针对枚举类型的 Set 接口的实现类它是处理枚举类型数据的一把利器非常高效的。从名字上也可以看得出EnumSet 不仅和 Set 有关系也和枚举有关系。
因为 EnumSet 是一个抽象类所以创建 EnumSet 时不能使用 new 关键字但是 EnumSet 提供了很多有用的静态工厂方法。
举个例子我们可以使用 noneOf) 静态工厂方法创建一个空的 Season 类型的 EnumSet使用 allOf() 静态工厂方法创建一个包含所有 Season 类型的 EnumSet
/*** author qiaohaojie* date 2023/3/22 22:41*/
public class SeasonClassTest {public static void main(String[] args) {EnumSetSeason enumSetNone EnumSet.noneOf(Season.class);System.out.println(enumSetNone); // []EnumSetSeason enumSetAll EnumSet.allOf(Season.class);System.out.println(enumSetAll); // [SPRING, SUMMER, AUTUMN, WINTER]}
}有了 EnumSet 后就可以使用 Set 的一些方法了
02、EnumMap
EnumMap 是一个专门针对枚举类型的 Map 接口的实现类它可以将枚举常量作为键来使用。EnumMap 的效率甚至比 HashMap 还要高可以直接通过数组下标枚举的 ordinal 值访问到元素。
与 EnumSet 不同的是EnuMap 不是一个抽象类所以创建 EnumMap 时可以使用 new 关键字
/*** author qiaohaojie* date 2023/3/22 22:41*/
public class SeasonClassTest {public static void main(String[] args) {EnumMapSeason, String enumMap new EnumMapSeason, String(Season.class);enumMap.put(Season.SPRING, 春天);enumMap.put(Season.SUMMER, 夏天);enumMap.put(Season.AUTUMN, 秋天);enumMap.put(Season.WINTER, 冬天);System.out.println(enumMap); // {SPRING春天, SUMMER夏天, AUTUMN秋天, WINTER冬天}}
}