枚举enum必知必会

内容大纲

  • 常规范式——替代int保安全
  • 高阶范式——实现单例模式
  • 复杂范式——实现方法
  • Android中的替代方案——IntDef/StringDef
  • 纯 Java中的替代方案——MagicConstant

常规范式

  • 取代int常量,确保类型安全性

可以看到,上例中,直接使用1,2之类的int值编译器是会报错的,因为enum是一种class,不止具有int值这一属性

相较于int值,enum会有类型安全检查,代码会更安全

高阶范式

  • 实现单例模式

这样实现的单例模式,不需要处理线程同步的问题,相较于传统的懒汉-饿汉-doublecheck的优势显而易见

实际上单例模式特别容易导致内存泄露,应该尽量减少使用,用更易用的架构设计模式来避免使用单例模式

复杂范式

  • 添加成员变量

在利用这一属性时,我们可以直接将enum当成一个类来使用,不一样的地方在于,enum的各项是直接给出了实例化的instance,所以带参构造函数需要我直接在定义中给出初始化参数(如上例中的hour)

  • 提供有差异的API

如上图所示,DayType的两个类型,各自实现了free方法,实现了差异化的API,这一属性可以用于策略模式,针对不同的类型,我们的enum可以提供不同的策略算法,满足差异化的需求

  • 实现接口

上面的抽象方法free,也可以抽象成接口形式,让枚举去实现,这一特性在工程中的应用极为有利,这样一来,就与我们的“面向接口编程”对上号了

注意API的访问级别需要升级为public

Android中的替代办法

我们都知道Android的内存非常宝贵,纵使enum有如此多的优点,但我们有时可能只想用它的一个替代int的属性,来增强代码的安全性,有没有其它更轻量的办法的?

答案是有的,@IntDef, @StringDef就能满足这一要求(属于注解范畴),以IntDef为例:

扒一扒IntDef的源码,我们会发现它其实自己也是一个注解,我们上例中应用的是它的value域,还可以利用的有flag域,鉴于flag一般都不会使用,不做过多介绍

Java模块中的替代办法

有的同学可能碰到这样的业务需要:

实际的工程是纯Java的,根本无法使用Android中的注解,这时该怎么办?

好吧,其实是我自己碰到这样的问题了,解决方案其实也很容易找到,查IntDef的设计思路,可以找到它的出处,最后的解决lib是

1
org.intellij.lang.annotations.MagicConstant

可以看到,这一lib是intellij的注解,感谢伟大的程序员们的杰作intellij

与IntDef不一样的地方在于:

  • 需要添加intValues关键字,不可以省略(IntDef中对应的可省略关键字是value)
  • 具体的值可以相同(IntDef中不可以)
  • 值变为String类型时只需要改关键字为 stringValues

get

enum还有一些特性,比如ordinal()取值、初始值从0开始、用EnumSet/EnumMap代替序数

实际也不推荐使用(ordinal取值不确定性强,程序稳定性差,实在要使用可以用成员变量代替)

Powered by KyleCe

Copyright © 2015 - 2019 KyleCe All Rights Reserved.

访客数 : | 访问量 :