web-dev-qa-db-ja.com

JavaでEnum finalのcompareToがなぜですか?

Javaの列挙型はComparableインターフェースを実装します。ComparablecompareToメソッドをオーバーライドするのは良いことですが、ここではfinalとしてマークされています。 。EnumcompareToのデフォルトの自然順序はリストされた順序です。

Java列挙型にこの制限がある理由を誰もが知っていますか?

85
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);    

さらに詳しい情報:

116
Zach Scrivena

ソースコードの順序を使用する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は、ソースコードライターを不必要にバインドしました。

35
Thomas Paine

列挙値は、宣言された順序に従って論理的に正確に順序付けられます。これは、Java言語仕様の一部です。したがって、列挙値は、同じEnumのメンバーである場合にのみ比較できます。仕様は、 compareTo()は、値が宣言された順序と同じであり、列挙の定義そのものです。

6
Martin OConnor

考えられる説明の1つは、compareToequalsと一貫している必要があるということです。

列挙型のequalsは、同一性と一致する必要があります(==)。

compareToがファイナルではない場合、equalsと一貫性のない振る舞いでオーバーライドすることができますが、これは非常に直感的ではありません。

2
Lii