为什么在Java中的Enum final上是compareTo?

Java中的枚举实现了Comparable接口。 重写ComparablecompareTo方法会很好,但是在这里它被标记为final。 EnumcompareTo上的默认自然顺序是列出的顺序。

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

为了一致性,我猜…当你看到一个enumtypes时,你知道一个事实 ,它的自然sorting是常量被声明的顺序。

要解决这个问题,您可以轻松创build自己的Comparator<MyEnum> ,并在需要不同的sorting时使用它:

 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 c = new MyEnumComparator(); int order = c.compare(MyEnum.CAT, MyEnum.DOG); 

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

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

更多信息:

  • 关于枚举types的Java教程
  • Sun的枚举指南
  • 类Enum API

提供使用源代码sorting的compareTo的默认实现是好的; 让它最终成为了Sun的一个失误。 序号已经占申报单。 我同意,在大多数情况下,开发人员可以在逻辑上对其元素进行sorting,但有时候希望将源代码组织起来,从而使可读性和维护成为至关重要的一部分。 例如:

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

上面的顺序在源代码中看起来不错,但不是作者认为compareTo应该如何工作的。 所需的compareTo行为是按字节数进行sorting。 源代码sorting会导致代码组织的恶化。

作为一个枚举的客户端,我并不在乎作者如何组织他们的源代码。 尽pipe如此,我还是希望他们的比较algorithm具有某种意义。 Sun已经不必要地将源代码编写者绑定了。

枚举值按照它们声明的顺序在逻辑上精确sorting。 这是Java语言规范的一部分。 因此,枚举值只有在它们是同一枚举的成员时才可以进行比较。 规范要进一步保证compareTo()返回的可比顺序与声明值的顺序相同。 这是一个枚举的定义。

一个可能的解释是compareTo应该和equals一致。

equals enums应与身份相等( == )一致。

如果compareTo在哪里是非最终的,就可以用一个与equals不一致的行为来覆盖它,这将是非常不直观的。

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