Вопрос

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

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

Это было полезно?

Решение

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

Дальнейшая информация:

Другие советы

Предоставление реализации 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, что было бы очень нелогично.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top