概念
Java枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。我们定义枚举类就是把具体的对象一个一个列举出来。
所谓枚举是指将变量的值一一列举出来,变量只限于列举出来的值的范围内取值。
实际开发中,常常定义一些不常更改的常量。
枚举的来源
一个现象是:一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,比如:方向,性别,星期,季节。这也是一个问题!
在Java5之前,是采用自定义带有枚举功能的类解决的,我们定义有些复杂常量会这么写:就是自定义一个类,然后是私有化构造函数,在自定义类中创建本类的对象对外使用。如下例子
class Gender{
String value;
public static final Gender man = new Gender("男");
public static final Gender woman = new Gender("女");
private Gender(String value) {
super();
this.value = value;
}
}
在Java5对以上问题提出了新的解决方案:就是使用枚举类解决。
enum Gender{
man("男"),
woman("女"),
;
String value;
private Gender(String value) {
this.value = value;
}
}
示例
Java枚举类使用enum关键字来定义,各个常量(实例)使用逗号 , 来分割。
public enum Color
{
RED, GREEN, BLUE,;
}
枚举类(Enum)的细节
1.枚举类也是一个特殊的类。
2.枚举值默认的修饰符是public static final
3.枚举值是枚举值所属的类的类型,然后枚举值是指向了本类的对象的。
4.枚举类的构造方法默认的修饰符是private。
5.枚举类可以定义自己的成员变量与成员函数。
6.枚举类可以自定义构造函数,但是构造函数的修饰符必须是private。
7.枚举类可以存在抽象的方法,但是枚举值必须要实现抽象的方法。
8.枚举值必须要位于枚举类的第一个语句。
9.enum定义的枚举类默认继承了java.lang.Enum类,并实现了java.lang.Serializable和java.lang.Comparable两个接口。由于Java不支持多继承,所以枚举类对象不能再继承其他类。
相关方法
values()
values()返回含有定义的所有枚举对象数组。
ordinal()
ordinal()输出的是该枚举对象的次序/编号/索引/下标,从0开始编号。
valueOf()
根据定义的name去找定义的枚举实例,如果找到了,就返回这个对象的具体信息,如果没有找到,就报错。
name()
返回实例名。
getDeclaringClass()
返回实例所属的enum类型
compareTo()
枚举比较大小,返回结果实际上是该对象ordinal值减去入参ordinal值,两枚举实例如果相同则返回0。
常用场景
(一)常量
(二)switch
(三)向枚举中添加新字段、新方法、覆盖Enum的方法
(四)实现接口和使用接口组织枚举(Java多态)
枚举的扩展
EnumSet
java.util.EnumSet是枚举类型的高性能Set实现,它要求放入它的枚举常量必须属于同一枚举类类型。
与TreeSet/HashSet不同,EnumSet是一个抽象类,不能直接通过new新建。不过,EnumSet提供了若干静态工厂方法,可以创建EnumSet类型的对象。
相关方法
// noneOf方法会创建一个指定枚举类型的EnumSet,不含任何元素。创建的EnumSet对象的实际类型是EnumSet的子类
<E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType)
// 初始集合包括指定枚举类型的所有枚举值
<E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType)
// 初始集合包括枚举值中指定范围的元素
<E extends Enum<E>> EnumSet<E> range(E from, E to)
// 初始集合包括指定集合的补集
<E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s)
// 初始集合包括参数中的所有元素
<E extends Enum<E>> EnumSet<E> of(E e)
<E extends Enum<E>> EnumSet<E> of(E e1, E e2)
<E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3)
<E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4)
<E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5)
<E extends Enum<E>> EnumSet<E> of(E first, E... rest)
// 初始集合包括参数容器中的所有元素
<E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s)
<E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c)
我们以noneOf()为例
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Set<Day> weekend = EnumSet.noneOf(Day.class);
weekend.add(Day.SATURDAY);
weekend.add(Day.SUNDAY);
System.out.println(weekend);//weekend表示休息日,noneOf返回的Set为空,添加了周六和周日,所以输出为[SATURDAY, SUNDAY]
EnumMap
Map接口的实现,其key-value映射中的key是Enum类型。
java.util.EnumMap是专门为枚举类型定制的Map,EnumMap在使用上跟HashMap差不多,但是EnumMap的性能更好,所以,如果键为Enum类型时,建议使用EnumMap代替HashMap。
package com.pichen.collection;
import java.util.EnumMap;
import java.util.Map;
import java.util.Map.Entry;
enum Operate{
ADD, UPDATE, DELETE;
}
public class Main {
public static void main(String[] args) {
Map<Operate, String> map = new EnumMap<Operate, String>(Operate.class);
//put方法
map.put(Operate.ADD, "add operate");
map.put(Operate.UPDATE, "update operate");
map.put(Operate.DELETE, "delete operate");
//重写了toString方法
System.out.println(map);
//size方法
System.out.println(map.size());
System.out.println(map.containsKey(Operate.UPDATE));
System.out.println(map.containsValue("update operate"));
System.out.println(map.get(Operate.DELETE));
//remove
map.remove(Operate.UPDATE);
System.out.println(map);
//key集合
for(Operate operate:map.keySet()){
System.out.print(operate + " ");
}
System.out.println();
//value集合
for(String obj:map.values()){
System.out.print(obj + ",");
}
System.out.println();
//key-value集合
for(Entry<Operate, String> entry:map.entrySet()){
System.out.print(entry.getKey() + ": " + entry.getValue() + ", ");
}
}
}
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情