2016-01-05 27 views
13

classの名前をcaseの定数として使用するjava switchステートメントを使用したいと考えています。どういうわけか可能ですか?クラス名を複製する必要がありますか?java switch/case文でクラス名を使用できますか?

コードに続くのためのコンパイラエラー動作しません:http://goo.gl/KvsR6u

ケース式は定数式ここ

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)のオンラインデモです

+2

文字列を最終的なStringローカル変数に割り当てることはできますか? –

+1

どのJavaバージョンですか? Java 7/8で異なる結果が得られます。 – Marged

+0

@Marged私はJava 8を使用していますが、どちらのバージョンのソリューションにも興味があります。 – dedek

答えて

6

コンパイラのエラーは既にそれを言います。大文字と小文字のラベルは定数式でなければならず、クラスリテラルやその上に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; 
} 

これは、読者との関係を文書化しますが、ツールは、まだ実際の文字列の内容は、クラス名と一致していることを確認しません。しかし、達成したいことに応じて、文字列の内容がクラス名と一致するかどうかは現在無関係になるかもしれません...

+0

これは正解です:*ケースラベルは定数式でなければなりません。クラスリテラルもgetSimpleName()を呼び出した結果も定数式です* – dedek

+0

**コンパイル時定数式の説明**私はここで見つけることができます:http://stackoverflow.com/a/3827424/1857897 – dedek

+0

私は*クラスリテラル*は定数式だと思っていますが、 "+" MyClass1.class'はうまくいくはずです。 ... – dedek

8

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

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

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

+0

私はこのソリューションについて考えていましたが、より効率的な 'switch'はありませんでしたか? – dedek

+2

おそらく、すべてのクラス名に対して行が必要な場合はコードが読みにくくなり、すべての場合にはさらに少数のコードが読み込まれる可能性があります。あなたが得る最適化の数ナノ秒は、おそらく 'Map'を使ってできるコードのクリーンな価値がないでしょう –

+1

ああ、私は追加するのを忘れました。もし私が正しく覚えていれば、何かが最近変更されていない限り、文字列の 'switch'はちょうど[ハッシュコードをスイッチする](http://www.benf.org/other/cfr/java7switchonstring.html)です –

2

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; 
} 
+1

私は 'else if'文を本当に好きではありません。@ Sam-Sunの' Map'ベースの解説を参照してください。 – dedek

+0

は選択肢ですが、これはすべてのバージョンでサポートされているため、バージョンの依存関係を処理する必要はありません。 –

+1

この解決策の問題は、最悪の場合、あらゆる可能性を超えなければならないということです。そのため、人々は「スイッチ」を望んでいます。 – Leonmax

関連する問題