1. Overview
1.概述
When we work with Java, understanding and manipulating object types are fundamental skills. One common challenge is checking whether an object belongs to an Enum type.
当我们使用 Java 时,理解和操作对象类型是基本技能。一个常见的挑战是检查对象是否属于 Enum 类型。
In this quick tutorial, we’ll explore various approaches and best practices for determining if an object’s type is an enum.
在本快速教程中,我们将探讨确定对象类型是否为 enum 的各种方法和最佳实践。
2. Introduction to the Problem
2.问题介绍
Enumerated types, or enums, provide a powerful way to represent a fixed set of values within a distinct type. Dynamically confirming whether an object is of an enum type can be essential for writing robust and type-safe code.
枚举类型(或 enums,)提供了一种强大的方法,用于在一个独特的类型中表示一组固定的值。动态确认对象是否属于 enum 类型对于编写健壮和类型安全的代码至关重要。
For example, we have a simple enum:
例如,我们有一个简单的 enum:
enum Device {
Keyboard, Monitor, Mouse, Printer
}
Now, let’s say we have an object:
现在,假设我们有一个对象:
Object obj = Device.Keyboard;
As we can see, obj is declared in type Object. Our challenge is to check if its type is enum. In this tutorial, we’ll learn different ways to solve this problem. Also, we’ll use unit test assertions to verify the result.
我们可以看到,obj 是以 Object 类型声明的。 我们面临的挑战是检查它的类型是否为 enum. 在本教程中,我们将学习解决这一问题的不同方法。此外,我们还将使用单元测试断言来验证结果。
3. Using the instanceof Operator
3.使用 instanceof 操作符
We know all enums have the same super class: java.lang.Enum. The instanceof operator allows us to test whether an object is an instance of a particular class or interface.
我们知道 所有枚举都有相同的超类:java.lang.Enum。instanceof 操作符允许我们测试对象是否是特定类或接口的实例。
Therefore, we can leverage this operator to check if an object is of Enum type:
因此,我们可以利用该操作符来检查对象是否属于 Enum 类型:
Object obj = Device.Keyboard;
assertTrue(obj instanceof Enum);
4. Using the Enum.class.isInstance() Method
4.使用 Enum.class.isInstance() 方法
The Class.isInstance() method does the same as the instanceof operator. Since we want to check the Enum type, Enum.class.isInstance(obj) solves the problem:
Class.isInstance() 方法的作用与 instanceof 操作符相同。由于我们要检查 Enum 类型,Enum.class.isInstance(obj) 可以解决这个问题:
Object obj = Device.Keyboard;
assertTrue(Enum.class.isInstance(obj));
5. Using the Enum.class.isAssignableFrom() Method
5.使用 Enum.class.isAssignableFrom() 方法
Similar to the Class.isInstance() method, the Class.isAssignableFrom() method checks whether the class on the left side is the same or a supertype of the given Class parameter. These two methods have slight differences. However, it makes no difference if we use them to solve our problem:
与 Class.isInstance() 方法类似,Class.isAssignableFrom() 方法检查左侧的类是否与给定的 Class 参数相同或属于给定 Class 参数的超类。isAssignableFrom() 方法检查左侧的类是否与给定的 Class 参数相同或属于给定 Class 参数的超类型。但是,如果我们使用它们来解决我们的问题,则没有任何区别:
Object obj = Device.Keyboard;
assertTrue(Enum.class.isAssignableFrom(obj.getClass()));
6. The Class.isEnum() Approach
6.Class.isEnum() 方法
Another way to ascertain if a class represents an enum is by using the isEnum() method provided by the Class class:
另一种确定类是否代表 enum 的方法是 使用 Class 类提供的 isEnum() 方法:
Object obj = Device.Keyboard;
assertTrue(obj.getClass().isEnum());
This approach is pretty straightforward. However, it may fail to check some enum instances. So next, let’s take a closer at Class.isEnum()‘s pitfall.
这种方法非常简单。但是,它可能无法检查某些枚举实例。因此,接下来,让我们仔细看看 Class.isEnum() 的陷阱。
7. The Class.isEnum() Pitfall: Enum Instances With Body
7.Class.isEnum() 陷阱:带正文的 Enum 实例
We know enums can have custom methods. Further, enum instances can override these methods. Next, let’s see another enum example:
我们知道枚举可以拥有自定义方法。此外,枚举实例可以覆盖这些方法。接下来,我们来看另一个枚举示例:
enum Weekday {
Monday, Tuesday, Wednesday, Thursday, Friday,
Saturday {
@Override
boolean isWeekend() {
return true;
}
},
Sunday {
@Override
boolean isWeekend() {
return true;
}
};
boolean isWeekend() {
return false;
}
}
As the code above shows, Weekday has the isWeekend() method. By default, the method returns false. However, the Saturday and Sunday instances have overridden this method to return true.
如上面的代码所示,Weekday 具有 isWeekend() 方法。默认情况下,该方法返回 false。但是,Saturday 和 Sunday 实例已重载该方法,返回 true。
Next, let’s take the solutions we’ve learned to verify some Weekday instances and see if they can report the correct results. First, let’s take Monday:
接下来,让我们用学到的解决方案来验证一些 Weekday 实例,看看它们能否报告正确的结果。首先,让我们以 Monday 为例:
Object monday = Weekday.Monday;
assertTrue(monday instanceof Enum);
assertTrue(Enum.class.isInstance(monday));
assertTrue(Enum.class.isAssignableFrom(monday.getClass()));
assertTrue(monday.getClass().isEnum());
If we run the test, all four approaches work as expected. Next, let’s take the Sunday instance as the input and repeat the test:
如果我们运行测试,所有四种方法都能达到预期效果。接下来,让我们将 Sunday 实例作为输入,重复测试:
Object sunday = Weekday.Sunday;
assertTrue(sunday instanceof Enum);
assertTrue(Enum.class.isInstance(sunday));
assertTrue(Enum.class.isAssignableFrom(sunday.getClass()));
assertFalse(sunday.getClass().isEnum()); // <-- isEnum() check failed when Enum values with body
This time, Class.isEnum() doesn’t produce a correct answer. Next, let’s understand why this happened.
这一次,Class.isEnum()没有产生正确的答案。接下来,让我们了解一下出现这种情况的原因。
When an individual enum instance overrides a method, such as Saturday and Sunday in our example, an anonymous class that acts as a subclass of the enum gets created. In such cases, Sunday.getClass() returns the anonymous subclass instead of the Weekday class. Thus, calling isEnum() on the class yields false.
当一个单独的枚举实例重载一个方法时(例如我们示例中的 Saturday 和 Sunday ),将创建一个匿名类作为枚举的子类。在这种情况下,Sunday.getClass() 将返回匿名子类,而不是 Weekday 类。 因此,在该类上调用 isEnum() 将得到 false. 结果。
Therefore, we shouldn’t consider the Class.isEnum() approach as a robust solution to this problem.
因此,我们不应将 Class.isEnum() 方法视为解决这一问题的稳健方案。
8. Conclusion
8.结论
Determining if an object’s type is an enum is crucial for writing flexible and robust Java code. In this article, we’ve explored different approaches to performing the check:
确定对象的类型是否为 enum 对于编写灵活、健壮的 Java 代码至关重要。在本文中,我们探讨了执行检查的不同方法:
- The instanceof operator
- The Enum.class.isInstance() method
- The Enum.class.isAssignableFrom() method
Furthermore, we highlighted a potential pitfall with the enumValue.getClass().isEnum() check, emphasizing that its reliability diminishes when dealing with overridden methods within enum instances. So, we shouldn’t rely on this approach as a definitive solution.
此外,我们还强调了enumValue.getClass().isEnum()检查的潜在隐患,强调在处理枚举实例中的重载方法时,其可靠性会降低。因此,我们不应该依赖这种方法作为最终解决方案。
As always, the complete source code for the examples is available over on GitHub.
与往常一样,这些示例的完整源代码可在 GitHub 上获取。