1. 概述
Java 5 引入了枚举(Enums),提供了一种安全且整洁的方式来管理常量。在这篇快速教程中,我们将探讨如何比较一个String
对象与枚举对象。
2. 问题介绍
首先,让我们看一个枚举的例子:
enum Weekday {
Mon("Monday"),
Tue("Tuesday"),
Wed("Wednesday"),
Thu("Thursday"),
Fri("Friday"),
Sat("Saturday");
private String fullName;
Weekday(String fullName) {
this.fullName = fullName;
}
public String getFullName() {
return fullName;
}
}
如代码所示,Weekday
枚举包含六个由每个工作日缩写命名的常量,并且它有一个名为fullName
的属性,用于存储每个工作日的完整名称。
现在假设我们有一个字符串s
。那么,将s
与枚举实例进行比较可能有以下两种情况:
- 将
s
与枚举实例的名称进行比较 - 将
s
与枚举实例的一个String
属性进行比较
本教程将涵盖这两种场景,并进行不区分大小写的比较。为了简化,我们将使用单元测试断言来验证比较结果。
接下来,我们创建两个String
作为输入:
final String SAT = "sAt";
final String SATURDAY = "sAtuRdAy";
我们将使用SAT
字符串进行枚举名称的比较,使用SATURDAY
变量进行枚举属性的比较。为了完整,我们还需要为负测试创建另外两个String
:
final String TYPO_FRI = "ffri";
final String TYPO_FRIDAY = "ffriday";
理解如何比较String
和枚举实例后,我们还将讨论这些比较的常见用例。现在,让我们实际操作一下。
3. 比较给定的String
与枚举实例的名称或属性
首先,我们来看看如何将给定的String
与枚举实例的名称进行比较。
**所有枚举类都继承自抽象类java.lang.Enum
**。这个抽象类定义了一个name()
方法,用于返回枚举实例的名称:
public abstract class Enum<E extends Enum<E>> implements Constable, Comparable<E>, Serializable {
private final String name;
...
public final String name() {
return this.name;
}
...
因此,我们可以使用name()
方法获取枚举常量的名称,并与给定的String
进行比较:
assertTrue(SAT.equalsIgnoreCase(Sat.name()));
assertFalse(TYPO_FRI.equalsIgnoreCase(Fri.name()));
如上面的测试所示,我们使用了equalsIgnoreCase()
方法进行不区分大小写的比较。
我们提到过,根据需求,我们可能想要将String
与枚举常量的属性(如Weekday
的fullName
属性)进行比较。这并不困难,因为Weekday
枚举有一个获取属性值的方法:
assertTrue(SATURDAY.equalsIgnoreCase(Sat.getFullName()));
assertFalse(TYPO_FRI.equalsIgnoreCase(Fri.getFullName()));
所以,正如我们所见,无论哪种场景,将String
与枚举进行比较都非常直接。
但在实际应用中,我们会在什么情况下需要这种比较呢?让我们通过例子来讨论。
4. 通过给定的String
查找枚举实例
一个常见的需要比较的情况是根据给定的String
确定枚举实例。例如,我们想通过字符串“SAT”找到Weekday.Sat
常量。
接下来,我们在Weekday
枚举中添加两个“查找”方法:
enum Weekday {
Mon("Monday"),
...
static Optional<Weekday> byNameIgnoreCase(String givenName) {
return Arrays.stream(values()).filter(it -> it.name().equalsIgnoreCase(givenName)).findAny();
}
static Optional<Weekday> byFullNameIgnoreCase(String givenFullName) {
return Arrays.stream(values()).filter(it -> it.fullName.equalsIgnoreCase(givenFullName)).findAny();
}
...
}
这两个方法的实现非常相似。一个用于按名称查找,另一个用于按fullName
属性查找。
我们在实现中使用了流(Stream API)。首先,values()
是一个静态方法,它在任何枚举类型中可用,并返回对应枚举类型的所有枚举常量数组。因此,Weekday.values()
给我们提供了所有的Weekday
常量。
然后,我们将常量数组转换为Stream
对象。接下来,我们将不区分大小写的比较逻辑传递给filter()
方法,作为lambda表达式。
由于我们不确定filter()
方法是否能找到匹配的枚举实例,我们返回findAny()
方法的结果,这是一个Optional<Weekday>
对象。调用者可以根据这个Optional
结果决定下一步的操作。现在,让我们看看在测试方法中它是如何工作的:
Optional<Weekday> optResult = Weekday.byNameIgnoreCase(SAT);
assertTrue(optResult.isPresent());
assertEquals(Sat, optResult.get());
Optional<Weekday> optResult2 = Weekday.byNameIgnoreCase(TYPO_FRI);
assertFalse(optResult2.isPresent());
如上述测试所示,只有当byNameIgnoreCase()
方法找到一个常量时,Optional
结果的isPresent()
才会返回true
。
这与“通过属性查找枚举常量”的场景非常相似。为了完整性,我们为byFullNameIgnoreCase()
方法创建一个测试:
Optional<Weekday> optResult = Weekday.byFullNameIgnoreCase(SATURDAY);
assertTrue(optResult.isPresent());
assertEquals(Sat, optResult.get());
Optional<Weekday> optResult2 = Weekday.byFullNameIgnoreCase(TYPO_FRIDAY);
assertFalse(optResult2.isPresent());
5. 总结
在这篇文章中,我们学习了如何比较String
与枚举常量。此外,我们通过示例讨论了比较的常见用例。
如往常一样,这里展示的所有代码片段都可以在GitHub上找到。