通俗易懂讲枚举

枚举使用关键字 enum 进行定义,每个元素都是一个实例,如下,FOO 和 BAR 都是一个 EnumClazz 实例。

public enum EnumClazz {
    FOO,
    BAR;
}

枚举类默认继承 Enum 类。

方法添加

我们可以给枚举实例添加一些对自身的描述,这是通过构造函数实现的

public enum EnumClazz {
    FOO("this is foo"),
    BAR("this is bar");

    EnumClazz(String desc) {
    }
}

但是这样是拿不到 desc 信息的,需要为其添加一个获取 desc 的方法。

public enum EnumClazz {
    FOO("this is foo"),
    BAR("this is bar");

    private String desc;

    private String getDesc(){
        return desc;
    }

    EnumClazz(String desc) {
        this.desc = desc;
    }
}

values 方法

我们定义的枚举类都是继承自 Enum 类,但是 Enum 类并没有 values() 方法,那么 values() 方法是怎么来的呢,答案是编译器自动帮我们生成的。 values() 方法可以获取到枚举类的所有实例,下面是常规使用方法:

value() 方法是接收一个 code 值,获取对应的枚举实例。

public enum EnumClazz {
    FOO(1),
    BAR(2);

    private Integer code;

    private Integer getCode() {
        return code;
    }

    EnumClazz(Integer code) {
        this.code = code;
    }

    public EnumClazz value(Integer code) {
        if (code == null) return null;
        for (EnumClazz value : EnumClazz.values()) {
            if (Objects.equals(value.getCode(), code)) {
                return value;
            }
        }
        return null;
    }
}

EnumSet

枚举类的每个实例其实都维护着一个顺序值,按照定义顺序来递增

EnumSet 采用 bit 位来实现,内部是使用 Long 类型来维护的,哪个枚举被塞入 EnumSet ,那么对应的 bit 位就制为1,由于是采用 bit 位进行操作的,因此速度非常快。Long 只有 64 位,但是 EnumSet 却可以存储超过 64 个枚举实例,估摸着是采用了多个 Long。

public enum EnumClazz {
    FOO,
    BAR;
    public static void main(String[] args) {
        System.out.println(EnumClazz.FOO.ordinal());
        System.out.println(EnumClazz.BAR.ordinal());
        EnumSet set = EnumSet.allOf(EnumClazz.class);
        System.out.println(set.contains(EnumClazz.FOO));
    }
}

输出:

0
1
true

EnumMap

EnumMap 的 key 只能是枚举,由于枚举的特殊性,每个实例都有自己的一个顺序值,可以用来定位,因此,直接采用数值来实现即可,我们知道,在知道数组下标的情况下,数组的顺序是非常快的。

public enum EnumClazz {
    FOO,
    BAR;
    public static void main(String[] args) {
        EnumMap map = new EnumMap(EnumClazz.class);
        map.put(EnumClazz.FOO, "foo");
        map.put(EnumClazz.BAR, "bar");
        System.out.println(map);
    }
}

输出:

由于每个属性都是一个枚举实例,那么,我们是不是可以在枚举类中定义方法,然后在实例中实现他们,从而采取不同的行为呢,就像多态那样。这是可以做到的(描述的有点乱,直接看代码,代码一看就懂)。

如下,在枚举类 EnumClazz 中定义一个抽象方法,在每个实例,在这里是 FOO 实例和 BAR 实例中实现改方法即可。当然,不是抽象方法也行。

public enum EnumClazz {
    FOO {
        @Override
        void showInfo() {
            System.out.println("I am foo");
        }
    },
    BAR {
        @Override
        void showInfo() {
            System.out.println("I am bar");
        }
    };

    abstract void showInfo();

    public static void main(String[] args) {
        EnumClazz.BAR.showInfo();
        EnumClazz.FOO.showInfo();
    }
}

输出:

I am bar
I am foo

在 Java 编程思想中,看到一个有意思的枚举使用方式,特此记录下来。

有时候,我们多个枚举类,但是这些枚举类又属于同一个大类目。举个栗子,水果下面分为香蕉、苹果、西瓜,香蕉分为米蕉、芝麻蕉、李林蕉,苹果分为:红玉苹果、金冠苹果、国光苹果,西瓜分为麒麟西瓜、黑美人西瓜、特小凤西瓜。其中可以创建水果枚举,香蕉枚举,苹果枚举,西瓜枚举,其中香蕉、苹果、西瓜枚举分别管理各自的品种,而水果枚举则管理着香蕉、苹果、西瓜枚举。也就是枚举的枚举。

这样的管理方式可以使用接口组织枚举

接口组织枚举

如下栗子,感觉还挺有意思的。

public enum FruitEnum {
    BANANA(FruitInterface.Banana.class),
    APPLE(FruitInterface.Apple.class),
    WATERMELON(FruitInterface.Watermelon.class);

    FruitInterface[] fruits;

    FruitEnum(Class clazz) {
        fruits = clazz.getEnumConstants();
    }

    interface FruitInterface {
        enum Banana implements FruitInterface {
            MI,
            LILIN,
            SESAME;
        }

        enum Apple implements FruitInterface {
            CARBUNCLE,
            GOLDEN_ROWN,
            GUO_GUANG;
        }

        enum Watermelon implements FruitInterface {
            QILIN,
            BLACK_BEAUTY,
            TE_XIAO_FENG
        }
    }

    public static void main(String[] args) {
        Random ran = new Random();
        FruitEnum[] fruits = FruitEnum.class.getEnumConstants();
        FruitEnum fruit = fruits[ran.nextInt(3)];
        FruitInterface[] randomFruits = fruit.fruits;
        for (FruitInterface item : randomFruits) {
            System.out.println(item);
        }
    }
}

QILIN
BLACK_BEAUTY
TE_XIAO_FENG

Original: https://www.cnblogs.com/cyrus-s/p/15458706.html
Author: 三木同学
Title: 通俗易懂讲枚举

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/715183/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球