web-dev-qa-db-ja.com

Java switch / caseステートメントでクラス名を使用することは可能ですか?

Java switchステートメントを使用します。これは、classの名前をcase定数として使用します。何らかの方法で可能ですか?またはクラス名を複製する必要がありますか?

コンパイラエラーのため、次のコードは機能しません:

ケース式は定数式でなければなりません

String tableName = "MyClass1";

...

switch (tableName) {
case MyClass1.class.getSimpleName():
    return 1;
case MyClass2.class.getSimpleName():
    return 2;
default:
    return Integer.MAX_VALUE;
}

これは問題のオンラインデモです(openjdk 1.8.0_45): http://goo.gl/KvsR6

19
dedek

コンパイラエラーはすでにそれを言っています。ケースラベルは定数式である必要があり、クラスリテラルも、getSimpleName()を呼び出した結果も定数式ではありません。

有効な解決策は次のとおりです。

_String tableName = "MyClass1";
...
switch (tableName) {
    case "MyClass1":
        return 1;
    case "MyClass2":
        return 2;
    default:
        return Integer.MAX_VALUE;
}
_

MyClass1.class.getSimpleName()は_"MyClass1"_よりも単純ではありませんが、もちろん、名前が既存のクラスと一致するかどうかのコンパイル時チェックは行われず、リファクタリングツールまたは難読化ツールは、クラス_MyClass1_と文字列リテラル_"MyClass1"_の関係。

それに対する解決策はありません。問題を軽減するためにできる唯一のことは、関係を文書化するために関連するクラス内でキーを宣言することです。

_class MyClass1 {
    static final String IDENTIFIER = "MyClass1";
    ...
}
class MyClass2 {
    static final String IDENTIFIER = "MyClass2";
    ...
}
...
String tableName = MyClass1.IDENTIFIER;
...
switch (tableName) {
    case MyClass1.IDENTIFIER:
        return 1;
    case MyClass2.IDENTIFIER:
        return 2;
    default:
        return Integer.MAX_VALUE;
}
_

これは読者との関係を文書化しますが、ツールは実際の文字列の内容がクラス名と一致することを保証しません。ただし、達成したいことによっては、文字列の内容がクラス名と一致するかどうかは、今は無関係になるかもしれません…

11
Holger

スイッチを使用する代わりに、マッピングをマップに保存してみませんか?

StringからIntegerへのマップを作成し、すべてのクラス名をそれらの戻り値にマップします。

リクエストで、エントリが存在しない場合は、デフォルト値を返します。それ以外の場合は、マップ内の値を返します。

8
Sam Sun

Switch..caseの代わりに、If..Elseを使用しないでください。 Javaのすべてのバージョンで動作するはずです。

if (tableName.equals(MyClass1.class.getSimpleName())) {
     return 1;
} else if (tableName.equals(MyClass2.class.getSimpleName())) {
     return 2;
} else {
     return Integer.MAX_VALUE;
}
3
Rajen Raiyarela