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);
さらに詳しい情報:
ソース コードの順序付けを使用する 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() によって返される比較可能な順序が、値が宣言された順序と同じであることをさらに保証したいと考えています。これはまさに列挙の定義です。
列挙型の要素の自然な順序を変更したい場合は、ソース コードでそれらの順序を変更します。