なぜJavaのswitch case文には、integer、short、byte、characterのみが使用され、他のデータ型は使用されないのですか?何が利益になるか?詳しく説明してください。なぜJavaのswitchcase文がこのように機能するのですか?
答えて
通常、言語の設計に関する質問は、「これがデザイナーがやることにしたのだから」と言います。これはそれらの時代のちょうど別のものです。
しかし、JavaはCでも同じことをしていました.80年代には、コンパイラがスイッチをジャンプテーブルに変える可能性があるため、その決定が私に説明されました。基本的に、コードの各ブロックテーブルに入れられ、switch
は、アドレスを取得するために渡した値を使ってテーブル参照(通常は配列または少なくともリンクされた配列のリストへのインデックス付け)が行われた後、そのアドレスにジャンプする範囲チェックになります。このシナリオでは整数だけが意味を持ちます。コンピュータはいつもと同じ速さではなかったことを忘れないでください。 Cは、コンピュータがはるかに低速だった60年代後半の作業に基づいて、70年代初期に設計されました。
JavaScriptなどのJavaやCと同じ構文伝統のいくつかの言語、if...else/if...else
を書くのswitch
ちょうど別の方法を作ると種類を制限するものではないが、おそらくので、で設計され、整数型にチェックされています90年代、それは現実的な選択肢になった。 JavaScriptの設計者(Brendan Eich)がそのように好まれたからかもしれません。以下は
、Baadshahは尋ねる:
好奇心から:それから、今どのようにそれをサポートする文字列を???あなたは何らかのアイデアをお願いしますか?
num = Integer.parseInt(args[0]); switch (num) { case 1: System.out.println("You used the special value one"); break; case 42: System.out.println("You used the special value forty-two"); break; case 67: System.out.println("You used the special value sixty-seven"); break; default: System.out.println("You used the a non-special value " + num); break; }
このようなバイトコードを生成します:
まずは、バックステップとint
ケースを見てみましょう
19: iload_2 20: lookupswitch { // 3 1: 56 42: 67 67: 78 default: 89 } 56: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 59: ldc #9 // String You used the special value one 61: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 64: goto 114 67: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 70: ldc #11 // String You used the special value forty-two 72: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 75: goto 114 78: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 81: ldc #12 // String You used the special value sixty-seven 83: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 86: goto 114 89: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 92: new #13 // class java/lang/StringBuilder 95: dup 96: invokespecial #14 // Method java/lang/StringBuilder."":()V 99: ldc #15 // String You used the a non-special value 101: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 104: iload_2 105: invokevirtual #17 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 108: invokevirtual #18 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 111: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
我々は行動にint
にテーブルルックアップを見ることができます。
それでは、文字列でどうやってやっていますか?さて、1つの答えはswitch
をif...else if...else
構造に変換することです。しかし、彼らはより多くの巧妙な何かをした:彼らは最適化するのにハッシュコードを使用して、衝突から保護するためにequals
を使用:
switch (str) {
case "abc":
System.out.println("You used the special value 'abc'");
break;
case "def":
System.out.println("You used the special value 'def'");
break;
case "ghi":
System.out.println("You used the special value 'ghi'");
break;
default:
System.out.println("You used the a non-special value '" + str + "'");
break;
}
は次のようになります。
124: aload 4 126: invokevirtual #19 // Method java/lang/String.hashCode:()I 129: lookupswitch { // 3 96354: 164 99333: 180 102312: 196 default: 209 } 164: aload 4 166: ldc #20 // String abc 168: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 171: ifeq 209 174: iconst_0 175: istore 5 177: goto 209 180: aload 4 182: ldc #22 // String def 184: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 187: ifeq 209 190: iconst_1 191: istore 5 193: goto 209 196: aload 4 198: ldc #23 // String ghi 200: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 203: ifeq 209 206: iconst_2 207: istore 5 209: iload 5 211: tableswitch { // 0 to 2 0: 236 1: 247 2: 258 default: 269 } 236: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 239: ldc #24 // String You used the special value 'abc' 241: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 244: goto 299 247: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 250: ldc #25 // String You used the special value 'def' 252: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 255: goto 299 258: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 261: ldc #26 // String You used the special value 'ghi' 263: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 266: goto 299 269: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 272: new #13 // class java/lang/StringBuilder 275: dup 276: invokespecial #14 // Method java/lang/StringBuilder."":()V 279: ldc #27 // String You used the a non-special value ' 281: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 284: aload_3 285: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 288: ldc #28 // String ' 290: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 293: invokevirtual #18 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 296: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
は、彼らが何をしたかを参照してください?基本的に2つのswitches
です:ハッシュコードに基づいて各ケースごとに一意の番号を取得します(ただし、equals
で二重チェックします)。次に2番目にディスパッチします。
好奇心から:それでは、どうやってそのサポート文字列???あなたは何らかのアイデアをお願いしますか? –
@Baadshah:とても良い質問です!私はそれに対処するために更新しました。 –
Crowder.Awsome簡単なコメントのおかげでありがとう。 –
JDK6 switch文は、char、byte、intのプリミティブなデータ型と列挙型を処理します。 JDK 7では、java.lang.Stringも定数であり、switch文でサポートされているデータ型のリストに追加されていることを認識しました。
たとえば、次のコードはJDK7で正常に動作します。
public static void OpenSource(String language)
{
switch (language) {
case "PERL":
System.out.println("PERL");
break;
case "Python":
System.out.println("Python");
break;
case "Ruby":
System.out.println("Ruby");
break;
case "PHP":
System.out.println("PHP");
break;
default:
throw new IllegalArgumentException();
}
}
- 1. なぜこの「if文」が機能しないのですか?
- 2. これはなぜ機能しないのですか? Java
- 3. なぜarray_merge_recursiveはこのように機能しますか?
- 4. Java:なぜ私のbreak文が機能しないのですか?
- 5. この例で条件文が機能しないのはなぜですか?
- 6. この準備文がMYSQLIで機能しないのはなぜですか?
- 7. Javaなぜ各ループでこれが機能しないのですか?
- 8. どのようにjavaのimport文は機能しますか?
- 9. なぜこのようなココアタッチの主な機能テンプレートですか?
- 10. dblclickイベントがclickイベントのように機能するのはなぜですか?
- 11. なぜ 'keydown'イベントが 'keypress'イベントのように機能するのですか?
- 12. javascript - なぜこのif文が機能しないのですか?
- 13. なぜこのChrome拡張機能が機能しないのですか?
- 14. このクイックソート機能が機能しないのはなぜですか?
- 15. WriteProcessMemoryのような機能が利用できるのはなぜですか?
- 16. JavaのgetGenericSuperclass()。どのように機能するのですか?
- 17. なぜこの変換が機能しないのですか?
- 18. このセレクタが機能しないのはなぜですか?
- 19. なぜこのメイクファイルが機能しないのですか?
- 20. なぜこのbashショートカットが機能しないのですか?
- 21. なぜこのPL/SQLが機能しないのですか?
- 22. なぜこのjqueryセレクタが機能しないのですか?
- 23. なぜこのリダイレクトが機能しないのですか?
- 24. このカレンダーが機能しないのはなぜですか?
- 25. なぜこのxpathが機能しないのですか?
- 26. このマップが機能しないのはなぜですか?
- 27. なぜこのRewriteRuleが機能しないのですか?
- 28. なぜこのドロップダウンが機能しないのですか?
- 29. なぜこのclearIntervalが機能しないのですか?
- 30. なぜこのSparqlクエリが機能しないのですか
また、JDK 1.7以降の文字列と列挙を受け付けます。 –
これは言語要件です。 Java 7の下では 'String'をサポートし、' enum'が導入されたので 'enum'もサポートしています。疑問は実際にどのように任意のオブジェクトのケースを定義するだろうか? – MadProgrammer
@MadProgrammerそれでは、任意のオブジェクトを作成し、equalsを使用して、私が推測するそれぞれのケースにマッチさせることができます。 – Thihara