Почему compareTo на финале Enum в Java?

Перечисление в Java реализует интерфейс Comparable. Было бы неплохо переопределить метод Comparable compareTo, но здесь он был отмечен как окончательный. Естественным порядком по умолчанию на Enum compareTo является указанный порядок.

Кто-нибудь знает, почему это перечисление Java перечисляет?

Ответ 1

Для согласованности, я думаю... когда вы видите тип 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);    

Дополнительная информация:

Ответ 2

Обеспечение реализации по умолчанию 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 состоит в том, чтобы упорядочить количество байтов. Корректировка исходного кода, которая могла бы привести к ухудшению организации кода.

В качестве клиента перечисления мне было все равно, как автор организовал исходный код. Тем не менее, я хочу, чтобы их алгоритм сравнения имел какой-то смысл. Солнце излишне помещает писателей исходного кода в bind.

Ответ 3

Значения перечисления точно упорядочены логически в соответствии с объявленным им порядком. Это часть спецификации языка Java. Поэтому следует, что значения перечисления можно сравнить только в том случае, если они являются членами одного и того же Enum. Спецификация хочет далее гарантировать, что сопоставимый порядок, возвращаемый compareTo(), совпадает с порядком, в котором объявлены значения. Это само определение перечисления.

Ответ 4

Одно из возможных объяснений состоит в том, что compareTo должно соответствовать equals.

И equals для перечислений должны быть совместимы с равенством идентичности (==).

Если compareTo где быть нефиналидным, можно было бы переопределить его с поведением, которое не соответствовало бы equals, что было бы очень противоречивым.

Ответ 5

Если вы хотите изменить естественный порядок элементов перечисления, измените их порядок в исходном коде.