【问题标题】:Why Java Enum need to check class and declaringClass in compareTo method为什么 Java Enum 需要在 compareTo 方法中检查类和声明类
【发布时间】:2017-02-25 23:12:54
【问题描述】:

Enum 中的类型参数E 定义为<E extends Enum<E>>。那么为什么在 Enum 实现源 code 中,我们仍然需要在 compareTo 方法中检查 getClass()getDeclaringClass() 呢?当我在compareTo 中设置不同的枚举类型对象时,我认为编译器无法通过。

【问题讨论】:

    标签: java enums


    【解决方案1】:

    它涵盖了比较原始类型和values obtained via unsafe / unchecked casts and conversions(如Comparable,或Object a)的情况:

    static enum Fruit { Apple, Orange, Banana };
    static enum Animal { Cat, Dog, Horse };
    
    public static final void main (String[] args) throws Exception {   
        Enum f = Fruit.Apple;
        Enum a = Animal.Cat;
        f.compareTo(a);
    }
    

    在那里,compareTo 在显式 getDeclaringClass 比较时会失败,ClassCastException,因为它会毫无问题地通过第一个显式转换 (Enum other = (Enum)o)。

    至于比较getClass,它在该来源中被标记为“优化”。这是一种优化的原因是,如果value classes 相同,那么它们肯定来自同一个枚举,因此无需调用稍贵的getDeclaringClass。由于绝大多数枚举可能是简单的枚举(没有值类主体),因此针对这种情况进行了优化。

    【讨论】:

    • 这不仅仅是原始类型。如果您声明 fa 的类型为 Object,它也适用。
    • @StephenC 仅当aObject。如果fObject,那么您将没有f.compareTo 可用。此外,对于EnumObject 类型的a,异常堆栈跟踪实际上略有不同,因此在我在此答案中添加Object 的提及之前,我需要考虑如何用文字清楚地表达这一点。
    • 如果您将f 转换为Comparable<?>,您可以。 (好吧,Object 是错误的选择……我的错。)另外,请考虑Enum<?>,它在技术上不是原始类型(参见 JLS 4.8)。但我的观点是,“原始类型”并不是唯一的原因。
    • @StephenC 如果fComparable<?>f.compareTo(a); 将如何编译?
    • 也许更好的措辞是“通过不安全/未经检查的强制转换和转换获得的原始类型和值”。也许有一个脚注来提醒人们忽略那些编译器警告是不明智的......
    【解决方案2】:

    如果您使用 Enum 作为原始类型,它可以。例如在这个程序中:

    public static void main(String[] args) {
        Enum e = A.x; // All occurrences of E are erased to Enum
        e.compareTo(B.i); // B.i extends Enum, so this is fine
    }   
    
    enum A {x,y,z};
    enum B {i,j,k};
    

    【讨论】:

    • E 不是Enum。如果您尝试将Enum 提供为E,它将无法编译。只是没有E
    • @user2357112 是的,我试图改写它。这个想法是compareTo(E)的擦除是compareTo(Enum)
    猜你喜欢
    • 1970-01-01
    • 2010-10-05
    • 2012-08-17
    • 2011-04-16
    • 2023-03-27
    • 1970-01-01
    • 2018-01-22
    • 1970-01-01
    • 2012-04-05
    相关资源
    最近更新 更多