基本的枚举定义
enum
的全称为 enumeration
, 是 JDK 1.5
中引入的新特性,存放在 java.lang
包中。
定义:
package top.twolovelypig;
public enum EnumMain {
MON, TUE, WED, THU, FRI, SAT, SUN;
}
输出枚举值代码:
package top.twolovelypig;
public class Test {
public static void main(String[] args) {
for (EnumMain e : EnumMain.values()) {
System.out.println(e.toString());
}
}
}
enum对象基本方法
int compareTo(E o)
该方法用来比较枚举与指定对象的顺序public static void main(String[] args) {
//值为6,表明SUN在MON后面六位
System.out.println(EnumMain.SUN.compareTo(EnumMain.MON));
//值为-2,表明tue比thu小两位(tue在thu前面两位)
System.out.println(EnumMain.TUE.compareTo(EnumMain.THU));
//值为0,表示二者是一样的
System.out.println(EnumMain.MON.compareTo(EnumMain.MON));
}
需要注意的是这里比较的值是有大小和正负的,不是说后面的与前面的相比结果就是1,也有可能是其他正数,具体结果是几就需要看后面的枚举是在前面的枚举后几位
Class<E> ``**getDeclaringClass**()
返回与枚举常量的枚举类型相对应的class
对象package top.twolovelypig;
public class Test {
public static void main(String[] args) {
EnumMain enumMain = EnumMain.FRI;
System.out.println("getDeclaringClass(): " + enumMain.getDeclaringClass().getName());
}
}
输出的结果是类的全路径:
getDeclaringClass(): top.twolovelypig.EnumMain
String name()
返回此枚举常量的名称public static void main(String[] args) {
EnumMain enumMain = EnumMain.FRI;
System.out.println("name(): " + enumMain.name());
}
输出结果是:
name(): FRI
int ordinal()
返回枚举常量的序数(初始常量序数为0)public static void main(String[] args) {
EnumMain enumMain = EnumMain.FRI;
System.out.println("ordinal(): " + enumMain.ordinal());
}
输出结果是4,因为
FRI
是第五个,初始常量序数是0,所以输出结果是4String toString()
返回枚举常量的名称
给enum自定义属性和方法(带参数的enum)
enum
package top.twolovelypig;
public enum EnumMain {
MON("星期一", 1),
TUE("星期二", 2),
WED("星期三", 3),
THU("星期四", 4),
FRI("星期五", 5),
SAT("星期六", 6),
SUN("星期天",7);
// 成员变量
private String name;
private int index;
// 构造方法
private EnumMain(String name, int index) {
this.name = name;
this.index = index;
}
// 普通方法 根据index获取name
public static String getNameByIndex(int index) {
for (EnumMain c : EnumMain.values()) {
if (c.getIndex() == index) {
return c.name;
}
}
return null;
}
// 普通方法 根据index获取name
public static int getIndexByName(String name) {
for (EnumMain c : EnumMain.values()) {
if (c.name.equals(name)) {
return c.index;
}
}
return 0;
}
// get set 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
上面代码中getIndexByName()
方法中需要注意c.name
与c.getName()
的区别,c.name
获取的是中文比如星期三,而c.getName()
的结果是FRI。
测试代码,根据名称获取索引,根据索引获取名称等:
package top.twolovelypig;
public class Test {
public static void main(String[] args) {
EnumMain enumMain = EnumMain.FRI;
//普通get方法 输出结果是5
System.out.println(enumMain.getIndex());
//普通getName()方法 输出结果是星期五
System.out.println(enumMain.getName());
//根据index获取name 输出结果是星期三
System.out.println(EnumMain.getNameByIndex(3));
//根据name获取index 输出结果是3
System.out.println(EnumMain.getIndexByName("星期三"));
}
}
对枚举的理解
可能不好理解的就是上面具有参数的枚举,其实只需要记住一点,java中一切皆对象,可以把枚举页当做一个类,这样来看的话上面的代码可以写成下面这样:
package top.twolovelypig;
public class EnumMain {
// 成员变量
private String name;
private int index;
// 构造方法
private EnumMain(String name, int index) {
this.name = name;
this.index = index;
}
// get set 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
对于上面的类比较好理解吧,就是具有两个属性而已,然后呢就是一个私有构造方法以及get/set方法。而对于枚举中的这些声明
MON("星期一", 1),
TUE("星期二", 2),
WED("星期三", 3),
THU("星期四", 4),
FRI("星期五", 5),
SAT("星期六", 6),
SUN("星期天",7);
其实就是该枚举类的对象,每一个声明都是一个对象,也就是这里其实有七个对象,此时简单理解枚举与类的区别就是枚举中对象是数量固定,相当于在一开始就实例化了几个固定的对象而已。然后后面哪些根据key
获取name
,以及根据name
获取key
都是自己加的一些方法而已。
enumMap
以下内容来自《java编程的逻辑》这本书。
如果需要一个Map的实现类,并且建的类型为枚举类型,可以使用HashMap,但应该使用一个专门的实现类EnumMap。因为枚举类型有两个特征:
- 枚举所有可能的值时有限的并且是预定义的
- 所有的枚举值有一个顺序
这两个特征可以更为高效的实现Map接口。
案例
比如有一批关于衣服的记录,想要通过尺寸统计衣服的数量,定义一个简单的枚举类Size
;都表示衣服的尺寸。
Size
枚举:
public enum Size{
SMALL, MEDIUM, LARGE
}
Clothes
类
class Clothes{
String id;
Size size;
//get与set
}
按尺寸统计数量:
public static Map<Size, Integer> countBySize(List<Clothes> clothes){
Map<Size, Integer> map = new EnumMap(Size.class);
for(Clothes c : clothes){
Size size = c.getSize();
Integer count = map.get(size);
if(count != null){
map.put(size, count+1);
}else{
map.put(size, 1);
}
}
}
需要注意EnumMap的构造方法
Map<Size, Integer> map = new EnumMap(Size.class);
EnumMap
需要传递一个类型信息,Size.class
表示枚举类Size
的运行时信息,需要这个参数是因为EnumMap
要知道具体的枚举类是什么。
测试代码:
List<Clothes> clothes = Arrays.asList(
new Clothes[]{
new Clothes("c001", Size.SMALL),
new Clothes("c002", Size.MEDIUM),
new Clothes("c003", Size.LARGE),
new Clothes("c004", Size.SMALL),
new Clothes("c005", Size.MEDIUM),
new Clothes("c006", Size.LARGE)
}
);
System.out.println(countBySize(clothes));
需要说明的是,EnumMap
是保证顺序的,输出是按照键在枚举中的顺序的。
enum的另外两个构造方法
除了以上介绍的构造方法,EnumMap还有两个构造方法,可以接受一个键值匹配的EnumMap或普通Map,如下所示:
public EnumMap(EnumMap<K, ? extends V> m)
public EnumMap(Map<K, ? extends V> m)
比如:
Map<Size,Integer> hashMap = new HashMap<>();
hashMap.put(Size.LARGE, 2);
hashMap.put(Size.SMALL, 1);
Map<Size, Integer> enumMap = new EnumMap<>(hashMap);