Перечисление в Java реализует Comparable
интерфейс. Было бы хорошо , чтобы переопределить Comparable
«s compareTo
метод, но здесь он помечен как окончательный. Естественный порядок по умолчанию на Enum
«s compareTo
является перечисленным порядком.
Кто-нибудь знает, почему у перечислений Java есть это ограничение?
java
enums
comparable
compareto
neu242
источник
источник
Ответы:
Думаю, для согласованности ... когда вы видите
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 без надобности связывает разработчиков исходного кода.
источник
Значения перечисления точно упорядочены логически в соответствии с порядком их объявления. Это часть спецификации языка Java. Следовательно, значения перечисления можно сравнивать, только если они являются членами одного и того же Enum. Спецификация хочет дополнительно гарантировать, что сопоставимый порядок, возвращаемый функцией compareTo (), совпадает с порядком, в котором были объявлены значения. Это само определение перечисления.
источник
Одно из возможных объяснений состоит в том, что оно
compareTo
должно соответствоватьequals
.И
equals
для перечислений должно быть согласовано равенство идентичности (==
).Если
compareTo
бы он не был окончательным, его можно было бы переопределить с помощью поведения, которое не соответствовало быequals
, что было бы очень нелогично.источник
Если вы хотите изменить естественный порядок элементов перечисления, измените их порядок в исходном коде.
источник