java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言, 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台 (即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se)) 的总称
enum 的全称为 enumeration, 是 JDK 1.5 中引入的新特性, 存放在 java.lang 包中下面这篇文章是我在使用 enum 过程中的一些经验和总结, 分享出来方便大家快速的掌握 Java 中枚举(enum), 有需要的朋友们下面跟着小编来一起看看吧
什么是枚举?
枚举是 JDK5 引入的新特性在某些情况下, 一个类的对象是固定的, 就可以定义为枚举在实际使用中, 枚举类型也可以作为一种规范, 保障程序参数安全枚举有以下特点:
Java 中枚举和类接口的级别相同
枚举和类一样, 都有自己的属性方法构造方法, 不同点是: 枚举的构造方法只能是 private 修饰, 也就无法从外部构造对象构造方法只在构造枚举值时调用
使用 enum 关键字声明一个枚举类型时, 就默认继承自 Java 中的 java.lang.Enum 类, 并实现了
java.lang.Seriablizable
和
java.lang.Comparable
两个接口
所有的枚举值都是 public static final 的, 且非抽象的枚举类不能再派生子类
枚举类的所有实例 (枚举值) 必须在枚举类的第一行显式地列出, 否则这个枚举类将永远不能产生实例
判断枚举是否相同时, 使用 == 和 equals 是一样的
下面是 java.lang.Enum 类中的 equals() :
- // 这里是 final 修饰的, 不允许子类重写
- public final boolean equals(Object other) {
- return this==other;
- }
枚举的常用方法
int compareTo(E o)
比较此枚举与指定对象的顺序在该对象小于等于或大于指定对象时, 分别返回负整数零或正整数 枚举常量只能与相同枚举类型的其他枚举常量进行比较
- // Enum 中的源码
- public final int compareTo(E o) {
- Enum other = (Enum)o;
- Enum self = this;
- if (self.getClass() != other.getClass() && // optimization
- self.getDeclaringClass() != other.getDeclaringClass())
- throw new ClassCastException();
- return self.ordinal - other.ordinal;
- }
- String name()
返回此枚举实例的名称
static values()
返回一个包含全部枚举值的数组, 可以用来遍历所有枚举值
String toString()
返回此枚举实例的名称, 即枚举值与 name() 一样
- // Enum 中 name() 和 toString()
- public String toString() {
- return name;
- }
- public final String name() {
- return name;
- }
- int ordinal()
返回枚举值在枚举类中的索引值(从 0 开始), 即枚举值在枚举声明中的顺序, 这个顺序根据枚举值声明的顺序而定
<T extends Enum<T>> valueOf()
返回带指定名称的指定枚举类型的枚举常量, 名称必须与在此类型中声明枚举常量所用的标识符完全匹配 (不允许使用额外的空白字符) 这个方法与 toString 相对应, 因此重写 toString()方法, 一定要重写 valueOf()方法 (我们可以重写 toString() 方法, 但不能自己重写 valueOf()方法, 当我们重写 toString()方法时, valueOf()方法会自动重写, 不用我们理会)
枚举的应用
枚举是一种特殊的类型, 其用法和普通的类使用非常相似
代替一组常量
- public enum Color {
- RED, GREEN, BLANK, YELLOW
- }
switch 语句中使用
- // JDK1.6 中 switch 加入了对枚举的支持
- enum Signal {
- GREEN, YELLOW, RED
- }
- ...
- switch (color) {
- case RED:
- color = Signal.GREEN;
- break;
- }
- ...
向枚举中添加方法
- public enum Color {
- RED("红色"), GREEN("绿色"), BLANK("白色"), YELLO("黄色");
- // 成员变量
- private String name;
- // 构造方法
- private Color(String name) {
- this.name = name;
- }
- // get set 方法
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
实现接口
- public interface Behaviour {
- void print();
- }
- public enum Color implements Behaviour{
- RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
- // 接口方法
- @Override
- public void print() {
- System.out.println(this.index+":"+this.name);
- }
- }
包含抽象方法的枚举类
- public enum Operation {
- // 用于执行加法运算
- PLUS { // 花括号部分其实是一个匿名内部子类
- @Override
- public double calculate(double x, double y) {
- return x + y;
- }
- },
- // 用于执行减法运算
- MINUS { // 花括号部分其实是一个匿名内部子类
- @Override
- public double calculate(double x, double y) {
- // TODO Auto-generated method stub
- return x - y;
- }
- },
- // 用于执行乘法运算
- TIMES { // 花括号部分其实是一个匿名内部子类
- @Override
- public double calculate(double x, double y) {
- return x * y;
- }
- },
- // 用于执行除法运算
- DIVIDE { // 花括号部分其实是一个匿名内部子类
- @Override
- public double calculate(double x, double y) {
- return x / y;
- }
- };
- // 为该枚举类定义一个抽象方法, 枚举类中所有的枚举值都必须实现这个方法
- public abstract double calculate(double x, double y);
- }
使用枚举实现单例(单例的最佳实践)
好处:
1. 利用的枚举的特性实现单例
2. 由 JVM 保证线程安全
3. 序列化和反射攻击已经被枚举解决
- public enum Singleton {
- INSTANCE;
- public Singleton getInstance(){
- // 增加这个方法是让别人明白怎么使用, 因为这种实现方式还比较少见
- return INSTANCE;
- }
- }
其他关于枚举的使用
- EnumSet
- range(E from, E to)
从枚举值中获取一段范围的 Set
- for(WeekDayEnum day : EnumSet.range(WeekDayEnum.Mon, WeekDayEnum.Fri)) {
- System.out.println(day);
- }
- of(E first, E... rest)
创建一个最初包含指定元素的枚举 Set
noneOf(Class<E> elementType)
创建一个具有指定元素类型的空枚举 Set
- EnumMap
- EnumMap(Class<K> keyType)
创建一个具有指定键类型的空枚举 Map
- Map<Weather, String> enumMap = new EnumMap<Weather, String>(Weather.class);
- enumMap.put(Weather.Sunny, "晴天");
- enumMap.put(Weather.Rainy, "雨天");
Android 中的枚举
Enum 需要占用较大的内存, 如果对内存敏感, 请尽量少使用 Enum, 换成静态常量
但是如果不使用枚举, 会出现一些安全隐患, 所以官方推出了两个注解, 可以在编译时期进行类型检查, 以此替代枚举这两个注解分别是:@IntDef 和 @StringDef 位于 compile 'com.android.support:support-annotations:+'
使用示例
@StringDef 的使用与 @IntDef 一致, 这里以 @IntDef 为例
- public interface QRCodeType {
- int WECHAT = 0;
- int ALIPAY = 1;
- @IntDef({WECHAT , ALIPAY })
- @Retention(RetentionPolicy.SOURCE)
- @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
- @interface Checker {
- }
- }
- public class QRCode {
- @QRCodeType.Checker // 定义在属性
- private int type;
- public void setType(@QRCodeType.Checker int type) { // 定义在参数
- this.type= type;
- }
- @QRCodeType.Checker // 定义在方法(也就是检查返回值的类型)
- public int getType() {
- return type;
- }
- }
使用建议
开发中使用范围最广的就是利用枚举代替一组静态常量, 这种情况可以使用以上注解方式替代
当枚举还含有其它功能时(如: 包含其它定义的方法), 则不能替换
总结
来源: http://www.phperz.com/article/18/0222/359223.html