3分钟快速掌握枚举(enum)

由于本人能力有限,文中若有错误之处,欢迎指正。
转载请注明出处:http://www.jianshu.com/p/6b7f715d06f6

什么是枚举?

枚举是JDK5引入的新特性。在某些情况下,一个类的对象是固定的,就可以定义为枚举。在实际使用中,枚举类型也可以作为一种规范,保障程序参数安全。枚举有以下特点

  1. Java中枚举和类、接口的级别相同。
  2. 枚举和类一样,都有自己的属性、方法、构造方法,不同点是:枚举的构造方法只能是private修饰,也就无法从外部构造对象。构造方法只在构造枚举值时调用。
  3. 使用enum关键字声明一个枚举类型时,就默认继承自Java中的 java.lang.Enum类,并实现了java.lang.Seriablizablejava.lang.Comparable两个接口。
  4. 所有的枚举值都是 public static final 的,且非抽象的枚举类不能再派生子类。
  5. 枚举类的所有实例(枚举值)必须在枚举类的第一行显式地列出,否则这个枚举类将永远不能产生实例。
  6. 判断枚举是否相同时,使用 == 和 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;
    }

}

使用建议

  1. 开发中使用范围最广的就是利用枚举代替一组静态常量,这种情况可以使用以上注解方式替代。
  2. 当枚举还含有其它功能时(如:包含其它定义的方法),则不能替换。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容