1. 概述

Java在1.5版本中引入了枚举(enum)。将常量定义为枚举可以使代码更易读,并且支持编译时检查。

在这篇简短教程中,我们将探讨如何获取一个包含枚举类型所有实例的List

2. 问题介绍

如常,我们通过一个例子来理解这个问题。

首先,创建一个枚举类型MagicNumber

enum MagicNumber {
    ONE, TWO, THREE, FOUR, FIVE
}

我们的目标是得到一个填充了MagicNumber枚举所有实例的List

List<MagicNumber> EXPECTED_LIST = Arrays.asList(ONE, TWO, THREE, FOUR, FIVE);

这里使用了Arrays.asList()方法从数组初始化列表,具体可以参考此处

接下来,我们将探讨几种不同的方法来获得预期的结果。最后,为了简化,我们将使用单元测试断言来验证每个方法是否给出了期望的结果。

现在,让我们看看它们是如何工作的。

3. 使用EnumType.values()方法

当我们准备EXPECTED_LIST时,它是从数组初始化的。因此,如果我们能从枚举类型中获取到数组中的所有实例,就可以构建列表并解决问题。

每个枚举类型都提供了标准的values()方法,用于返回所有实例组成的数组。接下来,让我们使用MagicNumber.values()构建列表:

List<MagicNumber> result = Arrays.asList(MagicNumber.values());
assertEquals(EXPECTED_LIST, result);

如果运行测试,它会通过。所以,我们得到了预期的列表。

4. 使用EnumType.class.getEnumConstants()方法

我们已经看到使用枚举类型的values()方法获取数组中的所有枚举实例。这是一种标准且直接的方法。然而,我们需要确切知道枚举类型的名称,并在代码中硬编码,例如MagicNumber.values()。换句话说,这种方式我们无法构建一个通用于所有枚举类型的工具方法。

自Java 1.5以来,**Class对象提供了getEnumConstants()方法,用于从枚举类对象获取所有枚举实例**。因此,我们可以让getEnumConstants()提供枚举实例:

List<MagicNumber> result = Arrays.asList(MagicNumber.class.getEnumConstants());
assertEquals(EXPECTED_LIST, result);

如上测试所示,我们使用MagicNumber.class.getEnumConstants()提供了枚举实例数组。此外,很容易构建一个适用于所有枚举类型的工具方法:

static <T> List<T> enumValuesInList(Class<T> enumCls) {
    T[] arr = enumCls.getEnumConstants();
    return arr == null ? Collections.emptyList() : Arrays.asList(arr);
}

值得一提的是,**如果Class对象不是枚举类型,getEnumConstants()方法将返回null**。正如我们所见,在这种情况下,我们返回一个空的List

接下来,让我们创建一个测试来验证enumValuesInList()

List<MagicNumber> result1 = enumValuesInList(MagicNumber.class);
assertEquals(EXPECTED_LIST, result1);
                                                                
List<Integer> result2 = enumValuesInList(Integer.class);
assertTrue(result2.isEmpty());

如果运行测试,它会通过。我们可以看到,如果类对象不是枚举类型,我们有一个空的List

5. 使用EnumSet.allOf()方法

自Java 1.5以来,引入了一种特殊的Set来处理枚举类:EnumSet。此外,EnumSet提供了allOf()方法来加载给定枚举类型的全部实例。

因此,我们可以使用ArrayList()构造函数和填充的EnumSet来构建List对象。现在,让我们通过一个测试来看看它是如何工作的:

List<MagicNumber> result = new ArrayList<>(EnumSet.allOf(MagicNumber.class));
assertEquals(EXPECTED_LIST, result);

值得注意的是,调用allOf()方法会按照自然顺序存储枚举的实例

6. 总结

在这篇文章中,我们学习了三种获取包含枚举类型所有实例的List对象的方法。

如往常一样,这里展示的所有代码片段都可以在GitHub上找到。