还在频繁定义常量?不试试用枚举代替(备战2022春招或暑期实习,每天进步一点点,打卡100天,Day5)

举报
李子捌 发表于 2021/11/01 09:14:41 2021/11/01
【摘要】 备战2022春招或暑期实习,祝大家每天进步亿点点!Day4本篇总结的是《Java 枚举的正确使用方式》,后续会每日更新~关于《Redis入门到精通》、《并发编程》等知识点可以参考我的往期博客相信自己,越活越坚强,活着就该逢山开路,遇水架桥!生活,你给我压力,我还你奇迹!1、简介不知道大家有没有在自己项目中看到过类似下面这样的代码:public static void fruitsHandle...
  • 备战2022春招或暑期实习,祝大家每天进步亿点点!Day5
  • 本篇总结的是《Java 枚举的正确使用方式》,后续会每日更新~
  • 关于《Redis入门到精通》、《并发编程》等知识点可以参考我的往期博客
  • 相信自己,越活越坚强,活着就该逢山开路,遇水架桥!生活,你给我压力,我还你奇迹!

751a8ffe445fbc514b868f41fb1efccd.jpeg


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;
    }

}


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



👇🏻 关注公众号 获取更多资料👇🏻

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。