古い方法では、複雑なビットマスクを使用したい場合は、次のswitch
ように簡単に実行できます (問題を示すためだけに頭のてっぺんからランダムに例を挙げました)。
private static final int MAN = 0x00000001;
private static final int WOMAN = 0x00000002;
// ...alive, hungry, blind, etc.
private static final int DEAD = 0xFF000000;
public void doStuff(int human) {
switch (human) {
case MAN | DEAD:
// do something
break;
// more common cases
}
}
最近ではenums
andを使っているのでEnumSets
、私は時々似たようなことをしたいと思います:
enum Human {
MAN, WOMAN, DEAD; // etc.
}
public void doStuff(EnumSet human) {
switch (human) {
case Human.MAN | Human.DEAD:
// do something
break;
// more common cases
}
}
switch
、または値int
でしかできないため、これは機能しません。この時点で、その値は基本的に単なる隠し整数であるにもかかわらず、実行できないことに気付きました。しかし、私は掘り下げるのが好きで、機能は非常に便利に見えるので、次のようにします。enum
String
enum
private static final EnumSet<Human> DEAD_MAN = EnumSet.of(Human.MAN, Human.DEAD);
public void doStuff(EnumSet human) {
switch (human) {
case DEAD_MAN:
// do something
break;
// more common cases
}
}
まだ運がありません。文字列を切り替えるためのトリックと、EnumSets が実際には 64 ビット フィールド (またはそれらの配列) であることを知っているので、次のことも試してみます。
switch (human.hashCode()) {
case (Human.MAN.hashCode() | Human.DEAD.hashCode()):
// do something
break;
// more common cases
}
Human
hashCode()
が適切に実装されて一貫した結果が得られれば、機能する可能性があると考えています。いいえ:
java.lang.Error:未解決のコンパイルの問題: ケース式は定数式でなければなりません
さて、なぜこれを行う可能性がないのだろうか。私は常に、Java で古い学校のビットフィールドの適切な代替品のように考えてenums
いEnumSets
ましたが、ここでは、新しい方法ではより複雑なケースを処理できないようです。
適切なソリューションの種類は、可能性のいずれかと比較して最悪ですswitch
。
public void doStuff(EnumSet human) {
if (human.contains(Human.MAN) && human.contains(Human.DEAD)) {
// do something
} else {
// more common cases
}
}
特に、 on が導入されて以来、switch
onStrings
には少なくとも 2 つの可能な実装があると思いswitch
ますEnumSets
。
- 式では、単純に列挙型自体の代わりに
case (Human.MAN | Human.DEAD)
コンパイル時の型チェックを使用します。ordinal()
- Strings と同じトリックを使用します。
- コンパイル時に、enum 値の を計算し
hashCode()
ますname
(そして、おそらく追加の何か - enum の値の数ordinal()
など - すべてはコンパイル時から静的で一定です)。はい、これはクラスまたはクラスのhashCode()
いずれかを変更することを意味します。EnumSet
Enum
- 列挙型自体の代わりに使用
- コンパイル時に、enum 値の を計算し
さて、これを簡単に実装することを不可能にする深刻な障害はありますか? それとも、これは実際に可能ですが、あまり頻繁に使用されないため、オラクルが実装するほど望ましくないというのは正しいでしょうか?
また、これは純粋に学術的な質問であり、適切な答えがない可能性があることを述べさせてください(わかりません。別の方法で質問することはありません)。答えられないことが判明した場合は、コミュニティ wiki にするかもしれません。しかし、私はどこにも答え(またはそれについて話し合っている人でさえ)を見つけることができなかったので、ここに行きます.