Javaの列挙型がComparable
インターフェースを実装します。Comparable
のcompareTo
メソッドをオーバーライドすると良かったのですが、ここではfinalとマークされています。上のデフォルトの自然な順序Enum
さんがcompareTo
リストされているためです。
Java列挙型にこの制限がある理由を誰かが知っていますか?
Javaの列挙型がComparable
インターフェースを実装します。Comparable
のcompareTo
メソッドをオーバーライドすると良かったのですが、ここではfinalとマークされています。上のデフォルトの自然な順序Enum
さんが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);
さらに詳しい情報:
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()によって返される比較可能な順序が、値が宣言された順序と同じであることをさらに保証したいと考えています。これがまさに列挙の定義です。
考えられる説明の1つは、compareTo
と一致する必要があるというものequals
です。
またequals
、列挙型はIDの等価性と一致している必要があります(==
)。
compareTo
最終でない場所を指定する場合、と一致しない動作でオーバーライドすることが可能でありequals
、直感に反することになります。
列挙型の要素の自然な順序を変更したい場合は、ソースコードでそれらの順序を変更します。