取代接口常量,Java中的枚举类型你都了解吗?

. 说明

枚举是一个带有命名的整型常数集合,用于声明一组带标识符的常数。枚举在曰常生活中,其实很常见,例如一个人的性别只能是“男”或者“女”,一周的星期只能是 7 天中的一个等等。当一个变量只有几种固定可取的值时,我们就可以将它定义为枚举类型。

在 JDK 1.5 之前没有枚举类型,那时候一般是用接口常量来替代,我们现在就可以用enum枚举类型来贴切地表示这种常量了。

. 为什么命名用枚举

1.需求分析

比如我们现在想编写一个游戏,游戏中有上下左右4个方向 ,我们可以创建一个类,在该类中定义出上下左右四个方向常量。

这时我们可以有以下几种实现方式。

2. 第一种实现方式

public class GameStaticFinal {
    //上
    public  static  final int  UP = 1; 
    //下
    public  static  final int DOWN = 2;
    //左
    public  static  final int LEFT = 3;
    //右
    public  static final  int RIGHT = 4;
}

缺点:

1. 代码中必须带有static final;

2. 1、2、3、4 这些命名都不能做到 “见名知意”。

3. 第二种实现方式

我们把上面的实现改造一下,把数字改成字符串。

public class GameStaticFinal {
    //上
    public  static  final String  UP = "UP";
    //下
    public  static  final String DOWN = "DOWN";
    //左
    public  static  final String LEFT = "LEFT";
    //右
    public  static final  String RIGHT = "RIGHT";
}

缺点:

1. 需要记住 "UP"、"DOWN" 这些英文字符串;

2. 用equals判断时,"UP".equals(GameStaticFinal. UP) ,"UP"写死了,这属于硬编码,不灵活。

看来以上两种实现方式都存在一些缺点,那我们可以怎么改进实现呢?这时候我们就可以用枚举来实现了。

. 定义枚举

1. 创建枚举类

public enum  GameEnum {
    UP, //上
    DOWN, //下
    LEFT, //左
    RIGHT; //右
}

2.使用注意事项

我们在使用枚举时,要注意以下几点:

  • 定义枚举时要使用Enum关键字;

  • 命名时类名尽量要带Enum , 常量全部大写,多个单词之间用_分割;

  • 枚举是一种特殊的常量类;

  • 默认的构造方法必须是私有的;

  • 枚举里的常量相当于枚举对象;

  • 常量之间用逗号分隔,用分号结尾。

具体应用

我们可以通过如下几个案例来展示枚举具体该怎么使用。

1.配合switch使用

我们可以在switch中配合枚举进行列举。

//获取里边的常量
Test01Enum e = Test01Enum.UP;
switch (e) {
    case UP:
        break;
    case LEFT:
        break;
    case DOWN:
        break;
    case RIGHT:
        break;
    case SKIP:
        break;
    default:
        break;
}

2.定义带参数的枚举常量

public enum Test03Enum {
    //四套:  success code msg 信息 整合的对象
    SELECT_SUCCESS(true,1001,"查询成功"),
    DELETE_SUCCESS(true,1002,"删除成功"),
    UPDATE_ERROR(false,1003,"更新失败"),
    ADD_ERROR(false,1004,"添加失败");
    //返回码:success  code  msg
    private  boolean success;
    private  int code;
    private  String msg;

    //构造器方法
    Test03Enum(boolean success, int code, String msg) {
        this.success = success;
        this.code = code;
        this.msg = msg;
    }

    public boolean isSuccess() {
        return success;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

}

测试使用:

public class Test03Main {
    public static void main(String[] args) {
        //1.获取有参构造器的枚举对象
        Test03Enum e = Test03Enum.SELECT_SUCCESS;

        System.out.println(e.isSuccess());
        System.out.println(e.getCode());
        System.out.println(e.getMsg());


    }
}

3.在集合中使用枚举

我们也可以把枚举作为集合的泛型,将集合与枚举结合一起使用。

public enum  Test07Enum {

    DOWN,UP,LEFT,SKIP,RIGHT;
}
public class Test07Main {

    public static void main(String[] args) {

        //1.创建一个泛型是枚举的集合
        List<Test07Enum>  list = new ArrayList<>();

        //2. 添加元素
        list.add(Test07Enum.UP);
        list.add(Test07Enum.UP);
        list.add(Test07Enum.DOWN);

        for (Test07Enum test07Enum : list) {
            System.out.println(test07Enum);
        }

        System.out.println("=======================================");
        //set 当中的元素是不重复的,所以,我可以去重
        // 利用 EnumSet可以去重
        EnumSet<Test07Enum> test07Enums = EnumSet.copyOf(list);
        System.out.println(test07Enums);

        System.out.println("=================================");
        // 利用 EnumSet  可以返回一个 EnumSet类型的集合 : 范围: 区间
        EnumSet<Test07Enum> range = EnumSet.range(Test07Enum.UP, Test07Enum.SKIP);
        System.out.println(range);


        System.out.println("EnumMap==========================");
        //EnumMap: key是枚举 类型  : 参数是枚举 的class类型

        EnumMap<Test07Enum,String>  map = new EnumMap<>(Test07Enum.class);
        map.put(Test07Enum.UP,"上");
        map.put(Test07Enum.DOWN,"下");

        String s = map.get(Test07Enum.UP);
        System.out.println(s);
        //EnumMap 数组结构 : 专门为 枚举 类型设计的map结构
    }

}

五. 枚举为什么是线程安全的?

我们去找工作时,有些面试官会考察关于枚举的内容,比如会问枚举是不是线程安全的,为什么?要想弄明白这个问题,我们可以使用一个命令来验证一下枚举类。

我们在控制台对某个字节码文件执行下面的命令之后,可以得到如下效果:

从上图中可以看出,枚举类最终会被编译为被final 修饰的普通类,我们知道常量就是用static final 来修饰的,所以枚举值就是常量值,无法被修改。另外枚举类在项目启动时就会被 JVM 加载并初始化,而这个执行过程肯定是线程安全的,所以枚举类也是线程安全的类。

猜你喜欢

转载自blog.csdn.net/finally_vince/article/details/128639754