Java中的枚举实现了该Comparable
接口。覆盖Comparable
的compareTo
方法会很不错,但是这里将其标记为final。在默认的自然秩序Enum
的compareTo
是所列出的顺序。
有谁知道为什么Java枚举有此限制?
Answers:
为了保持一致性,我想...当您看到一个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 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);
更多信息:
MyEnumComparator
没有状态,因此应该只是一个单例,特别是如果您正在执行@Bombe建议的操作;相反,您可以做一些事情MyEnumComparator.INSTANCE.compare(enum1, enum2)
以避免不必要的对象创建
LENGTH_COMPARATOR
枚举的静态字段中。这样,对于使用枚举的任何人来说都很容易找到。
提供使用源代码顺序的compareTo的默认实现是可以的;使它最终成为Sun的失误。序号已经说明了申报顺序。我同意,在大多数情况下,开发人员可以按逻辑顺序排列其元素,但有时人们希望以一种使可读性和维护性至高无上的方式来组织源代码。例如:
//===== 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不必要地将源代码编写者置于束缚之中。
一种可能的解释是 compareTo
应该与equals
。
和 equals
因为枚举应与身份相等一致(==
)。
如果compareTo
在哪里是非最终的,则可以用与不一致的行为来覆盖它equals
,这将是非常违反直觉的。
如果要更改枚举元素的自然顺序,请在源代码中更改其顺序。