【Java枚举enum】--- 基本使用

总览

在这里插入图片描述

前言

枚举在Java中得到了大量使用,例如Spring中关于事务传播性的org.springframework.transaction.annotation.Propagation,mybatis-plus中关于字段填充策略com.baomidou.mybatisplus.annotation.FieldFill。对于有限的数据值列举,基本都可以通过枚举来管理和使用。
在Java5之前,发挥同样作用的是使用final修饰的常量,但其存在一定的局限性,使用起来也没那么便利,同时存在许多缺点。通过对比现在enum的枚举类特性即可看出一二。enum枚举类存储着枚举值的索引、名称、所有枚举值等重要信息,并且可以将每一个枚举值视为一个对象,进行自定义扩展属性和方法。而使用final修饰的常量功能则没那么强大,此外还有其他的优点。

一、概念

1.1 定义
被enum关键字修饰的类型就是枚举类型。

1.2 例子

  • 最简单例子。不对Enum类进行属性方法扩展
public enum Sex {
   	// 女性
   	FEMALE,
 	// 男性
  	MALE;
}
  • 根据业务扩展类。对属性方法进行扩展。添加value属性和Sex()构造方法
public enum Sex {

    // 女性
    FEMALE(1),
    // 男性
    MALE(2);

    private int value;

    Sex(int value){
        this.value = value;
    }
    
    public int value(){
        return this.value;
    }
    
    @Override
    public String toString() {
        return "Sex{" +
                "value=" + value +
                '}';
    }
}

1.3 优点

  • 统一管理常量引用,值一处修改,引用处处修改
  • 减少传递参数错误,限制输入的数据范围。可通过枚举值判断参数是否在枚举范围内
  • Switch语句优势
  • …等等

1.4 场景
有限的数据范围值。错误码、状态机、mybatis-plus的填充策略、Spring中事务的传播性等。

1.5 本质
枚举的本质是 java.lang.Enum 的子类。

二、特性

  • 不能继承的其他类(已经继承java.lang.Enum),也不能被其他类继承
  • 可以添加属性和方法,普通方法、静态方法、抽象方法、构造方法
  • 不允许使用 = 为枚举常量赋值
  • 可以通过方法显示赋值

三、Enum类

枚举类在不扩展属性和方法的情况下,只有继承来自父类的属性和方法,可视为Enum类。

3.1 属性

属性含义
private final String name此枚举值使用时的直观名称
private final int ordinal与索引index类似,ordinal在枚举中表示的是枚举值定义时的一个次数,从0开始

3.2 方法

属性含义
values()返回 enum 所有实例的数组。而且该数组中的元素严格保持在 enum 中声明时的顺序。
name()返回实例名
ordinal()返回实例声明时的顺序,从0开始
getDeclaringClass()返回实例所属的全类名
equals()判断是否为同一个对象。(也可以使用==来比较enum实例,因为引用的是同一个堆地址)

3.3 实例:定义一个Sex枚举类,并且添加一个value属性,并添加获取value属性的 value()方法

// Sex枚举类
public enum Sex {

    // 女性
    FEMALE(1),
    // 男性
    MALE(2);
    // 扩展的value属性
    private int value;

    Sex(int value){
        this.value = value;
    }

    public int value(){
        return this.value;
    }

    @Override
    public String toString() {
        return "Sex{" +
                "value=" + value +
                '}';
    }
}

// 测试类
public class EnumTest {

    public static void main(String[] args) {
        // value() 扩展的方法
        System.out.println("value() :" + Sex.MALE.value());
        // values()
        System.out.println("values() :" + Arrays.toString(Sex.values()));
        System.out.println("values() :" + Arrays.toString(Sex.MALE.values()));
        // name()
        System.out.println("name() :" + Sex.MALE.name());
        // ordinal()
        System.out.println("ordinal() :" + Sex.MALE.ordinal());
        // getDeclaringClass()
        System.out.println("getDeclaringClass() :" + Sex.MALE.getDeclaringClass());
        // equals() 和 ==
        System.out.println("== :" + (Sex.MALE == Sex.MALE));
        System.out.println("equals() :" + Sex.MALE.equals(Sex.MALE));
        System.out.println("equals() :" + Sex.MALE.equals(Sex.FEMALE));
    }
}
// 结果
value() :2
values() :[Sex{value=1}, Sex{value=2}]
values() :[Sex{value=1}, Sex{value=2}]
name() :MALE
ordinal() :1
getDeclaringClass() :class com.ming.enumtest.Sex
== :true
equals() :true
equals() :false

四、工具类

为了更好地支持枚举类型,java.util 中添加了两个新类:EnumMapEnumSet。使用它们可以更高效地操作枚举类型。

4.1 EnumMap 类
EnumMap 是专门为枚举类型量身定做的 Map 实现。虽然使用其他的 Map(如 HashMap)实现也能完成枚举类型实例到值的映射,但是使用 EnumMap 会更加高效。

HashMap 只能接收同一枚举类型的实例作为键值,并且由于枚举类型实例的数量相对固定并且有限,所以 EnumMap 使用数组来存放与枚举类型对应的值,使得 EnumMap 的效率非常高。

例子:
下面是使用 EnumMap 的一个代码示例。枚举类型 DataBaseType 里存放了现在支持的所有数据库类型。针对不同的数据库,一些数据库相关的方法需要返回不一样的值,例如示例中 getURL() 方法。

// 定义数据库类型枚举
public enum DataBaseType {
    MYSQUORACLE,DB2,SQLSERVER
}
// 某类中定义的获取数据库URL的方法以及EnumMap的声明
private EnumMap<DataBaseType,String>urls = new EnumMap<DataBaseType,String>(DataBaseType.class);
public DataBaseInfo() {
    urls.put(DataBaseType.DB2,"jdbc:db2://localhost:5000/sample");
    urls.put(DataBaseType.MYSQL,"jdbc:mysql://localhost/mydb");
    urls.put(DataBaseType.ORACLE,"jdbc:oracle:thin:@localhost:1521:sample");
    urls.put(DataBaseType.SQLSERVER,"jdbc:microsoft:sqlserver://sql:1433;Database=mydb");
}
//根据不同的数据库类型,返回对应的URL
// @param type DataBaseType 枚举类新实例
// @return
public String getURL(DataBaseType type) {
    return this.urls.get(type);
}

在实际使用中,EnumMap 对象 urls 往往是由外部负责整个应用初始化的代码来填充的。这里为了演示方便,类自己做了内容填充。

从本例中可以看出,使用 EnumMap 可以很方便地为枚举类型在不同的环境中绑定到不同的值上。本例子中 getURL 绑定到 URL 上,在其他的代码中可能又被绑定到数据库驱动上去。

EnumSet 类
EnumSet 是枚举类型的高性能 Set 实现,它要求放入它的枚举常量必须属于同一枚举类型。EnumSet 提供了许多工厂方法以便于初始化,如表 2 所示。

方法含义
allOf(Class<E> element type)创建一个包含指定枚举类型中所有枚举成员的 EnumSet 对象
complementOf(EnumSet<E> s)创建一个与指定 EnumSet 对象 s 相同的枚举类型 EnumSet 对象,并包含所有 s 中未包含的枚举成员
copyOf(EnumSet<E> s)创建一个与指定 EnumSet 对象 s 相同的枚举类型 EnumSet 对象,并与 s 包含相同的枚举成员
noneOf(<Class<E> elementType)创建指定枚举类型的空 EnumSet 对象
of(E first,e...rest)创建包含指定枚举成员的 EnumSet 对象
range(E from ,E to)创建一个 EnumSet 对象,该对象包含了 from 到 to 之间的所有枚举成员

EnumSet 作为 Set 接口实现,它支持对包含的枚举常量的遍历。

for(Operation op:EnumSet.range(Operation.PLUS,Operation.MULTIPLY)) {
    doSomeThing(op);
}

最后

枚举值相比于Java5之前使用类定义常量的方法具有很多使用的优点,非常有意义的升级。

引用文章
http://c.biancheng.net/view/1100.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值