代码之家  ›  专栏  ›  技术社区  ›  neu242

为什么Java中枚举上的compareTo是final?

  •  104
  • neu242  · 技术社区  · 17 年前

    Java中的枚举实现了 Comparable 界面。要是能推翻就好了 可比较的 s compareTo 方法,但这里它被标记为final。默认的自然顺序为 Enum s 比较函数 是列出的顺序。

    有人知道为什么Java枚举有这个限制吗?

    5 回复  |  直到 8 年前
        1
  •  123
  •   Zach Scrivena    17 年前

    为了保持一致性,我想。..当你看到一个 enum 类型,你知道的 确确实实 它的自然顺序是常量声明的顺序。

    为了解决这个问题,您可以轻松创建自己的 Comparator<MyEnum> 并在需要其他订购时使用它:

    enum MyEnum
    {
        DOG("woof"),
        CAT("meow");
    
        String sound;    
        MyEnum(String s) { sound = s; }
    }
    
    class MyEnumComparator implements Comparator<MyEnum>
    {
        public int compare(MyEnum o1, MyEnum o2)
        {
            return -o1.compareTo(o2); // this flips the order
            return o1.sound.length() - o2.sound.length(); // this compares length
        }
    }
    

    您可以使用 Comparator 直接:

    MyEnumComparator comparator = new MyEnumComparator();
    int order = comparator.compare(MyEnum.CAT, MyEnum.DOG);
    

    或者在集合或数组中使用它:

    NavigableSet<MyEnum> set = new TreeSet<MyEnum>(comparator);
    MyEnum[] array = MyEnum.values();
    Arrays.sort(array, comparator);    
    

    更多信息:

        2
  •  40
  •   Thomas Paine    16 年前

    提供使用源代码排序的compareTo的默认实现是可以的;最终进入决赛是孙的一个失误。序号已经考虑了声明顺序。我同意,在大多数情况下,开发人员可以对其元素进行逻辑排序,但有时人们希望源代码的组织方式能够使可读性和维护性变得至关重要。例如:

    
      //===== SI BYTES (10^n) =====//
    
      /** 1,000 bytes. */ KILOBYTE (false, true,  3, "kB"),
      /** 106 bytes. */   MEGABYTE (false, true,  6, "MB"),
      /** 109 bytes. */   GIGABYTE (false, true,  9, "GB"),
      /** 1012 bytes. */  TERABYTE (false, true, 12, "TB"),
      /** 1015 bytes. */  PETABYTE (false, true, 15, "PB"),
      /** 1018 bytes. */  EXABYTE  (false, true, 18, "EB"),
      /** 1021 bytes. */  ZETTABYTE(false, true, 21, "ZB"),
      /** 1024 bytes. */  YOTTABYTE(false, true, 24, "YB"),
    
      //===== IEC BYTES (2^n) =====//
    
      /** 1,024 bytes. */ KIBIBYTE(false, false, 10, "KiB"),
      /** 220 bytes. */   MEBIBYTE(false, false, 20, "MiB"),
      /** 230 bytes. */   GIBIBYTE(false, false, 30, "GiB"),
      /** 240 bytes. */   TEBIBYTE(false, false, 40, "TiB"),
      /** 250 bytes. */   PEBIBYTE(false, false, 50, "PiB"),
      /** 260 bytes. */   EXBIBYTE(false, false, 60, "EiB"),
      /** 270 bytes. */   ZEBIBYTE(false, false, 70, "ZiB"),
      /** 280 bytes. */   YOBIBYTE(false, false, 80, "YiB");
    

    上述排序在源代码中看起来不错,但作者认为compareTo不应该这样工作。理想的compareTo行为是按字节数排序。实现这一点的源代码顺序会降低代码的组织性。

    作为枚举的客户,我根本不在乎作者如何组织他们的源代码。不过,我确实希望他们的比较算法有某种意义。Sun不必要地使源代码编写者陷入困境。

        3
  •  6
  •   Martin OConnor    17 年前

    枚举值根据其声明的顺序在逻辑上精确排序。这是Java语言规范的一部分。因此,只有当枚举值是同一枚举的成员时,才能对其进行比较。该规范希望进一步保证compareTo()返回的可比顺序与声明值的顺序相同。这就是枚举的定义。

        4
  •  2
  •   Lii bob    10 年前

    一种可能的解释是 compareTo 应与 equals .

    同等的人 因为枚举应该与身份平等一致( == ).

    如果 比较函数 在非最终性的情况下,可以用与以下行为不一致的行为来覆盖它 同等的人 ,这将非常违反直觉。

        5
  •  -1
  •   Bombe    17 年前

    如果要更改枚举元素的自然顺序,请在源代码中更改它们的顺序。