• 还在频繁定义常量?不试试用枚举代替


    「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

    • 备战2022春招或暑期实习,祝大家每天进步亿点点!Day5

    • 本篇总结的是 《Java 枚举的正确使用方式》,后续会每日更新~

    • 关于《Redis入门到精通》、《并发编程》等知识点可以参考我的往期博客

    • 相信自己,越活越坚强,活着就该逢山开路,遇水架桥!生活,你给我压力,我还你奇迹!

    image.png

    1、简介

    不知道大家有没有在自己项目中看到过类似下面这样的代码:

    public static void fruitsHandle(String fruits) {
    
        switch (fruits) {
            case "Apple":
                // TODO
                break;
            case "Banana":
                // TODO
                break;
            case "Orange":
                // TODO
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + fruits);
        }
    
    }
    复制代码

    出现上面这种情况是非常少的,小萌新一般也不会直接在方法中重复定义字符串进行比较,而会将其定义为常量,或者统一抽取为常量类。所以一般会看到这种代码(小捌经常在项目中看到类似这样的代码,但是小捌不敢吭声):

    private static final String APPLE = "Apple";
    private static final String BANANA = "Banana";
    private static final String ORANGE = "Orange";
    
    public static void fruitsHandle(String fruits) {
    
        switch (fruits) {
            case APPLE:
                // TODO
                break;
            case BANANA:
                // TODO
                break;
            case ORANGE:
                // TODO
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + fruits);
        }
    
    }
    复制代码

    上面这种情况我们在代码中出现的频率非常高;它需要程序员提供一组固定常量,并且这一组固定常量在开发时或者说编译时就知道了具体的成员,这个时候我们就应该使用枚举。

    枚举类型(enum type)是指由一组固定常量组成合法值的类型。


    2、优势

    使用枚举类型,相比直接定义常量能够带来非常多的好处。


    2.1 类型安全

    分别定义一个简单的肉类枚举和水果枚举

    // 肉类枚举
    public enum MeetEnums {
    
        BEEF,
        PORK,
        FISH;
    
    }
    复制代码
    // 水果枚举
    public enum FruitsEnums {
    
        APPLE,
        BANANA,
        ORANGE;
    
    }
    复制代码

    我们改造上面的代码,修改入参类型即可

    public static void fruitsHandle(FruitsEnums fruits) {
    
        switch (fruits) {
            case APPLE:
                // TODO
                break;
            case BANANA:
                // TODO
                break;
            case ORANGE:
                // TODO
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + fruits);
        }
    
    }
    复制代码

    可以看到定义枚举类型带来函数类型安全性,如果定义的是常量则无法代理这种效果

    2.2 枚举能够提供更多信息

    枚举在本质上还是一个类,它能够定义属性和方法,我们可以在枚举类中定义想要的方法、或者通过属性扩展枚举提供的基础信息。

    比如我们做web开发时最常见的HttpStatus,在springframework框架中就被定义成了枚举类,它不仅包含了Http响应码,还能包含描述状态。

    public enum HttpStatus {
    
    	OK(200, "OK"),
        NOT_FOUND(404, "Not Found"),
        INTERNAL_SERVER_ERROR(500, "Internal Server Error");
        
        private final int value;
        private final String reasonPhrase;
    
        private HttpStatus(int value, String reasonPhrase) {
            this.value = value;
            this.reasonPhrase = reasonPhrase;
        }
        
    }
    复制代码

    2.3 通过函数提供更多服务

    此外HttpStatus它内部还嵌套了Series枚举类,这个类可以协助HttpStatus枚举类,通过statusCode / 100的模判断当前的枚举状态是is1xxInformational、is2xxSuccessful、is3xxRedirection、is4xxClientError、is5xxServerError等等。

    public static enum Series {
            INFORMATIONAL(1),
            SUCCESSFUL(2),
            REDIRECTION(3),
            CLIENT_ERROR(4),
            SERVER_ERROR(5);
    
            private final int value;
    
            private Series(int value) {
                this.value = value;
            }
    
            public int value() {
                return this.value;
            }
    
            public static HttpStatus.Series valueOf(HttpStatus status) {
                return valueOf(status.value);
            }
    
            public static HttpStatus.Series valueOf(int statusCode) {
                HttpStatus.Series series = resolve(statusCode);
                if (series == null) {
                    throw new IllegalArgumentException("No matching constant for [" + statusCode + "]");
                } else {
                    return series;
                }
            }
    
            @Nullable
            public static HttpStatus.Series resolve(int statusCode) {
                int seriesCode = statusCode / 100;
                HttpStatus.Series[] var2 = values();
                int var3 = var2.length;
    
                for(int var4 = 0; var4 < var3; ++var4) {
                    HttpStatus.Series series = var2[var4];
                    if (series.value == seriesCode) {
                        return series;
                    }
                }
    
                return null;
            }
        }
    复制代码

    2.4 获取所有定义的类型

    所有的枚举类会自动产生一个values()方法,它能返回当前定义枚举类的数组集,因此可以很方便的遍历怎么枚举类定义的所有枚举。比如我们简单改造一下MeetEnums枚举类:

    public enum MeetEnums {
    
        BEEF("牛肉"),
        PORK("猪肉"),
        FISH("鱼肉");
    
        String name;
    
        public String getName() {
            return name;
        }
    
        MeetEnums(String name) {
            this.name = name;
        }
    
        public static MeetEnums getMeetEnumsByName(String name) {
            MeetEnums[] values = values();
            Optional<MeetEnums> optional = Stream.of(values).filter(v -> v.getName().equals(name)).findAny();
            return optional.isPresent() ? optional.get() : null;
        }
    
    }
    复制代码

    总之枚举类相比常量来说有太多的优点,它能使得代码更加整洁美观、安全性强、功能强大。虽然大部分情况下,枚举类的选择是由于常量定义的,但是也并不是任何时候都一定要把常量定义成枚举;具体情况大家就可以自己去斟酌啦!

    来源:https://juejin.cn/post/7025394182210453540
  • 相关阅读:
    Android开发教程
    Java基础——多线程
    Android基础总结(10)——手机多媒体的运用:通知、短信、相机、视频播放
    Android基础总结(9)——网络技术
    Android基础总结(7)——异步消息处理
    Android基础总结(6)——内容提供器
    《App研发录》知识点汇总
    Android基础总结(5)——数据存储,持久化技术
    Android基础总结(4)——广播接收器
    Android基础总结(3)——UI界面布局
  • 原文地址:https://www.cnblogs.com/konglxblog/p/16756505.html
Copyright © 2020-2023  润新知