美文网首页
枚举类型总结

枚举类型总结

作者: tandeneck | 来源:发表于2018-05-12 16:34 被阅读0次

    前言

    枚举是 JDK 1.5 引入的类型,它使得我们在需要群组并使用枚举类型集时,可以很方便地处理。

    基本使用

    用法一:常量。
    public class EnumTest {
       /* static final int MONDAY = 0;
        static final int TUESDAY = 1;
        static final int WEDNESDAY = 2;
        static final int THURSDAY = 3;
        static final int FRIDAY = 4;
        static final int SATURDAY = 5;
        static final int SUNDAY = 6;*/
        enum Days{
            MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY
        }
    
        public static void main(String[] args) {
            for (Days days : Days.values()) {
                System.out.println(days.name() + " " + days.ordinal());
            }
        }
    }
    

    其实这种用法完全可以用常量来替换的嘛,但是仔细对比,如果常量多的时候,是不是用枚举更优雅,代码量更少一点呢?

    用法二:switch。我们知道,在 JDK 1.7 之前 switch 是不支持 String 类型的,但是如果我们有这个需求怎么解决呢?答案就是我们可以通过枚举来实现。
       public class SwitchStringByEnum {
    
        enum Days {
            MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
        }
    
        public static void printDay(String day) {
            try {
                Days days = Days.valueOf(day);
                switch (days) {
                    case MONDAY:
                        System.out.println(days.name());
                        break;
                    case TUESDAY:
                        System.out.println(days.name());
                        break;
                    case WEDNESDAY:
                        System.out.println(days.name());
                        break;
                    case THURSDAY:
                        System.out.println(days.name());
                        break;
                    case FRIDAY:
                        System.out.println(days.name());
                        break;
                    case SATURDAY:
                        System.out.println(days.name());
                        break;
                    case SUNDAY:
                        System.out.println(days.name());
                        break;
                    default:
                        break;
    
                }
            } catch (IllegalArgumentException e) {
                System.out.println("你的输入有误");
            }
        }
    
        public static void main(String[] args) {
            printDay("MONDAY");
            printDay("TUESDAY");
            printDay("WEDNESDAY");
            printDay("THURSDAY");
            printDay("FRIDAY");
            printDay("星期一");
            printDay("星期二");
            printDay("星期三");
            printDay("星期四");
        }
    }
    

    输出结果:


    image.png

    因为枚举的 valueOf 方法是根据给定的名字返回相应的 enum 实例,如果不存在给定名字的实例,就会抛出异常,我们可以捕捉这个异常,对输入的格式类型进行控制。当然,从 JDK 1.7 开始 switch 已经支持 String 类型了,我们没必要用这种笨拙的方式啦。

    用法三:用枚举实现单例模式。关于单例模式可以看下这篇文章
    public enum  Singleton {
        INSTANCE;
        public void doSomething(){
            System.out.println("Single Dog");
        }
    
        public static void main(String[] args) {
            Singleton.INSTANCE.doSomething();
        }
    }
    

    可以看出,用枚举实现单例是比较简单的,而且它确保了在任何情况下(包括反序列化、反射、克隆)下都是一个单例。因为枚举类是在第一次访问时才被实例化,所以它也是懒加载的。

    为什么使用枚举

    可以发现,前面三种用法我们都可以不使用枚举来实现,我们为什么还要使用枚举呢?

    1.首先是类型安全问题。比如用法一中的常量。

    static final int MONDAY = 0;
    static final int TUESDAY = 1;
    

    这样的定义的 MONDAY 和 TUESDAY 完全可以用来做加减运算,这与我们的本意相违背,如果我们使用枚举就可以解决这种问题啦。
    2.解决了意义不明确。比如调试程序时,本来想输出 MONDAY,结果输出了一个 0,如果不是自己写的完全不知道其意义。
    3.代码更优雅。这个前面已经提到过了,用枚举来代替常量不仅编码更少,而且更直观。

    Android 中的枚举使用

    首先,Android 官方是不推荐使用枚举类型的,因为与静态常量相比,它对内存的占用要大很多(官方说是2倍),还会增大 dex 文件。这是由于枚举的最终实现是类,在编译完成后,最终为每一种类型生成一个静态对象,而在内存申请方面,对象需要的内存空间远远大于普通的静态常量。不过还是要视情况而定啦,如果代码中只有少量的枚举,我们用少量的性能损耗就可以换来了代码更直观、类型安全等好处。而且如果开启 ProGuard 优化的情况下,枚举会被转为 int 类型,所以内存占用问题是可以忽略的,不过转换时有条件的,如果枚举类存在以下的情况,则不会优化为整型:

    • 枚举实现了自定义接口,并且被调用
    • 代码中使用了不同签名来存储枚举
    • 使用 instanceOf 关键字判断
    • 对枚举强转
    • 在代码中调用静态方法 valueOf 方法
    • 定义可以外部访问的方法。

    但是如果要对使用大量的枚举类型的项目进行优化时应该怎么做呢?这时可以使用常量加上 Android 中的 IntDef、StringDef 注解来实现类似枚举的效果。

    首先,需要在项目中添加一条依赖:

     compile 'com.android.support:support-annotations:latest-version'
    

    示例:

    public class MainActivity extends AppCompatActivity {
    
        public static final int RED = 1;
        public static final int GREEN = 2;
        public static final int BLUE = 3;
    
        @IntDef({RED,GREEN,BLUE})
        @Retention(RetentionPolicy.SOURCE)
        public @interface RGB{}
    
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            showRGB(RED);
            showRGB(GREEN);
            showRGB(BLUE);
            //提示错误
            showRGB(1);
            //提示错误
            showRGB(1232);
        }
    
        public static void showRGB(@RGB int color){
            System.out.println(String.valueOf(color));
        }
    }
    

    相关文章

      网友评论

          本文标题:枚举类型总结

          本文链接:https://www.haomeiwen.com/subject/mirvlftx.html