恕我直言,我怀疑你并不会用 Java 枚举(1)

简介: 恕我直言,我怀疑你并不会用 Java 枚举

开门见山地说吧,enum(枚举)是 Java 1.5 时引入的关键字,它表示一种特殊类型的类,默认继承自 java.lang.Enum。


为了证明这一点,我们来新建一个枚举 PlayerType:


public enum PlayerType {
    TENNIS,
    FOOTBALL,
    BASKETBALL
}

两个关键字带一个类名,还有大括号,以及三个大写的单词,但没看到继承 Enum 类啊?别着急,心急吃不了热豆腐啊。使用 JAD 查看一下反编译后的字节码,就一清二楚了。


public final class PlayerType extends Enum
{
    public static PlayerType[] values()
    {
        return (PlayerType[])$VALUES.clone();
    }
    public static PlayerType valueOf(String name)
    {
        return (PlayerType)Enum.valueOf(com/cmower/baeldung/enum1/PlayerType, name);
    }
    private PlayerType(String s, int i)
    {
        super(s, i);
    }
    public static final PlayerType TENNIS;
    public static final PlayerType FOOTBALL;
    public static final PlayerType BASKETBALL;
    private static final PlayerType $VALUES[];
    static 
    {
        TENNIS = new PlayerType("TENNIS", 0);
        FOOTBALL = new PlayerType("FOOTBALL", 1);
        BASKETBALL = new PlayerType("BASKETBALL", 2);
        $VALUES = (new PlayerType[] {
            TENNIS, FOOTBALL, BASKETBALL
        });
    }
}


看到没?PlayerType 类是 final 的,并且继承自 Enum 类。这些工作我们程序员没做,编译器帮我们悄悄地做了。此外,它还附带几个有用静态方法,比如说 values() 和 valueOf(String name)。


01、内部枚举


好的,小伙伴们应该已经清楚枚举长什么样子了吧?既然枚举是一种特殊的类,那它其实是可以定义在一个类的内部的,这样它的作用域就可以限定于这个外部类中使用。


public class Player {
    private PlayerType type;
    public enum PlayerType {
        TENNIS,
        FOOTBALL,
        BASKETBALL
    }
    public boolean isBasketballPlayer() {
      return getType() == PlayerType.BASKETBALL;
    }
    public PlayerType getType() {
        return type;
    }
    public void setType(PlayerType type) {
        this.type = type;
    }
}



PlayerType 就相当于 Player 的内部类,isBasketballPlayer() 方法用来判断运动员是否是一个篮球运动员。


由于枚举是 final 的,可以确保在 Java 虚拟机中仅有一个常量对象(可以参照反编译后的静态代码块「static 关键字带大括号的那部分代码」),所以我们可以很安全地使用“==”运算符来比较两个枚举是否相等,参照 isBasketballPlayer() 方法。


那为什么不使用 equals() 方法判断呢?


if(player.getType().equals(Player.PlayerType.BASKETBALL)){};

if(player.getType() == Player.PlayerType.BASKETBALL){};

1

2

“==”运算符比较的时候,如果两个对象都为 null,并不会发生 NullPointerException,而 equals() 方法则会。


另外, “==”运算符会在编译时进行检查,如果两侧的类型不匹配,会提示错误,而 equals() 方法则不会。


image.png


02、枚举可用于 switch 语句


这个我在之前的一篇我去的文章中详细地说明过了,感兴趣的小伙伴可以点击链接跳转过去看一下。


switch (playerType) {
        case TENNIS:
            return "网球运动员费德勒";
        case FOOTBALL:
            return "足球运动员C罗";
        case BASKETBALL:
            return "篮球运动员詹姆斯";
        case UNKNOWN:
            throw new IllegalArgumentException("未知");
        default:
            throw new IllegalArgumentException(
                    "运动员类型: " + playerType);
    }


03、枚举可以有构造方法


如果枚举中需要包含更多信息的话,可以为其添加一些字段,比如下面示例中的 name,此时需要为枚举添加一个带参的构造方法,这样就可以在定义枚举时添加对应的名称了。


public enum PlayerType {
    TENNIS("网球"),
    FOOTBALL("足球"),
    BASKETBALL("篮球");
    private String name;
    PlayerType(String name) {
        this.name = name;
    }
}


04、EnumSet


EnumSet 是一个专门针对枚举类型的 Set 接口的实现类,它是处理枚举类型数据的一把利器,非常高效(内部实现是位向量,我也搞不懂)。


因为 EnumSet 是一个抽象类,所以创建 EnumSet 时不能使用 new 关键字。不过,EnumSet 提供了很多有用的静态工厂方法:


image.png


下面的示例中使用 noneOf() 创建了一个空的 PlayerType 的 EnumSet;使用 allOf() 创建了一个包含所有 PlayerType 的 EnumSet。


public class EnumSetTest {
    public enum PlayerType {
        TENNIS,
        FOOTBALL,
        BASKETBALL
    }
    public static void main(String[] args) {
        EnumSet<PlayerType> enumSetNone = EnumSet.noneOf(PlayerType.class);
        System.out.println(enumSetNone);
        EnumSet<PlayerType> enumSetAll = EnumSet.allOf(PlayerType.class);
        System.out.println(enumSetAll);
    }
}



程序输出结果如下所示:


[]

[TENNIS, FOOTBALL, BASKETBALL]


有了 EnumSet 后,就可以使用 Set 的一些方法了:



相关文章
|
12天前
|
安全 Java 测试技术
🎉Java零基础:全面解析枚举的强大功能
【10月更文挑战第19天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
97 60
|
2月前
|
安全 Java 索引
Java——反射&枚举
本文介绍了Java反射机制及其应用,包括获取Class对象、构造方法、成员变量和成员方法。反射允许在运行时动态操作类和对象,例如创建对象、调用方法和访问字段。文章详细解释了不同方法的使用方式及其注意事项,并展示了如何通过反射获取类的各种信息。此外,还介绍了枚举类型的特点和使用方法,包括枚举的构造方法及其在反射中的特殊处理。
60 9
Java——反射&枚举
|
2月前
|
Java
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
79 5
|
2月前
|
安全 Java 开发者
Java 枚举(enum)详解
Java 中的枚举(`enum`)是一种特殊的数据类型,用于定义一组固定的常量,提升代码的类型安全性和可读性。枚举使用 `enum` 关键字定义,支持方法和构造函数,具有类型安全、单例、自动序列化等特点,并且可以遍历和用于 `switch` 语句中。实际应用包括状态机、指令集、类型标识等场景。枚举使代码更加清晰易维护。
|
3月前
|
Java
Java枚举使用的基本案例
这篇文章是关于Java枚举的基本使用,通过一个指令下发的代码案例,展示了如何定义枚举、使用枚举以及如何通过枚举实现指令的匹配和处理。
|
3月前
|
Java 开发者
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案。本文通过技术综述及示例代码,剖析两者在性能上的差异。if-else具有短路特性,但条件增多时JVM会优化提升性能;switch则利用跳转表机制,在处理大量固定选项时表现出色。通过实验对比可见,switch在重复case值处理上通常更快。尽管如此,选择时还需兼顾代码的可读性和维护性。理解这些细节有助于开发者编写出既高效又优雅的Java代码。
47 2
|
3月前
|
安全 Java 编译器
|
3月前
|
Java
【Java】内部类、枚举、泛型
【Java】内部类、枚举、泛型
|
3月前
|
设计模式 存储 安全
18 Java反射reflect(类加载+获取类对象+通用操作+设计模式+枚举+注解)
18 Java反射reflect(类加载+获取类对象+通用操作+设计模式+枚举+注解)
92 0
|
4月前
|
缓存 开发者 Java
java枚举消除冗余代码问题之需要延迟注册枚举到缓存问题如何解决
java枚举消除冗余代码问题之需要延迟注册枚举到缓存问题如何解决
下一篇
无影云桌面