为什么在Java中的Enum final上是compareTo?
Java中的枚举实现了Comparable
接口。 重写Comparable
的compareTo
方法会很好,但是在这里它被标记为final。 Enum
的compareTo
上的默认自然顺序是列出的顺序。
有谁知道为什么Java枚举有这个限制吗?
为了一致性,我猜…当你看到一个enum
types时,你知道一个事实 ,它的自然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
不一致的行为来覆盖它,这将是非常不直观的。
如果要更改枚举元素的自然顺序,请在源代码中更改它们的顺序。