2013-06-07 1 views
10

なぜJavaのswitch case文には、integer、short、byte、characterのみが使用され、他のデータ型は使用されないのですか?何が利益になるか?詳しく説明してください。なぜJavaのswitchcase文がこのように機能するのですか?

+6

また、JDK 1.7以降の文字列と列挙を受け付けます。 –

+2

これは言語要件です。 Java 7の下では 'String'をサポートし、' enum'が導入されたので 'enum'もサポートしています。疑問は実際にどのように任意のオブジェクトのケースを定義するだろうか? – MadProgrammer

+0

@MadProgrammerそれでは、任意のオブジェクトを作成し、equalsを使用して、私が推測するそれぞれのケースにマッチさせることができます。 – Thihara

答えて

16

通常、言語の設計に関する質問は、「これがデザイナーがやることにしたのだから」と言います。これはそれらの時代のちょうど別のものです。

しかし、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つの答えはswitchif...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番目にディスパッチします。

+3

好奇心から:それでは、どうやってそのサポート文字列???あなたは何らかのアイデアをお願いしますか? –

+1

@Baadshah:とても良い質問です!私はそれに対処するために更新しました。 –

+0

Crowder.Awsome簡単なコメントのおかげでありがとう。 –

1

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(); 
} 

}

関連する問題