JavaのSwitch StatementがCASEとしてFINAL変数を含む理由


2 Answers

switch(x){
    case 200: System.out.println("200"); break;
    case 300: System.out.println("300");
}

本質的には

if (x == 200)
  System.out.println("200");
else if (x == 300)
  System.out.println("300");

これは単なる比較であり、割り当てはないので、 xを変更できないということは重要ではありません。

技術的には、あなたは少し違うでしょう( breakがないので):

if (x == 200)
  System.out.println("200");
if (x == 200 || x == 300)
  System.out.println("300");

またはそのようなものです。

xが決して200または300ならないという事実は、コードをコンパイルしないようにしません。 しかし、Javaはswitch文を最適化することができます。

Question

JavaのSwitch StatementがCASEとしてFINAL変数を含む理由 ##

私がチェックしたJDK7では、以下のように、最終変数に値を再割当てすることはできません。 しかし、最終変数 "x"の値を再割当てすることはできませんが、最終変数 "x"をケースステートメントのSwitch Statementに含めることができる理由は何ですか?

なぜOracleは、Javaコンパイラが最終変数を初期化された値として取りますが、変数名は使用しないと定義していますか? http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4

これがJavaコンパイラの技術的なエラーであるか、またはスイッチステートメントの最終変数の大文字小文字の区別の例外または特別な使用があるかどうか教えてください。

class Example{
    public static void main(String args[]){
        final int x=100;
        //x=200;    //error: cannot assign a value to final variable x

        //The below piece of code compiles
        switch(x){
            case 200: System.out.println("200");
            case 300: System.out.println("300");
        }

    }
}



なぜあなたはfinal修飾子が違いを生み出すと思いますか? スイッチオンされている値には何も割り当てる必要はありません。

あなたはswitchステートメントが何を理解していますか?




ほとんどのコンパイラはヒューリスティック(経験ベースの手法)と近似に依存する最適化アルゴリズムを使用してコードを最適化します。 以下のコードはコントロールフローの分析になります。 私はプログラムのサンプルをたくさん走った

ケースA)最終変数を持つif-else - コンパイラは警告デッドコードを投げます。 生成されたバイトコードには、if-elseステートメントはありません。

public static void main(java.lang.String[])

Stack=1, Locals=2, Args_size=1
0:  iconst_0
1:  istore_1
2:  return
LineNumberTable: 
line 42: 0
line 54: 2

LocalVariableTable: 
Start  Length  Slot  Name   Signature
 0      3      0    args       [Ljava/lang/String;
 2      1      1    selection       I


 }

ケースB)if-else final variableなし - コンパイラエラーはなく、コード最適化もありません。

      final int selection i=100; //case A
      //int selection i=100; //case B

     if(selection==1){
         System.out.println("Hi");
  }else if(selection==2){

  }else{

   }

ケースC)if-elseを最終変数とするがif-else文を別のメソッドに入れる

       computeIfLese(int selection) 
  • このメソッドはパラメータの異なる値を持つ他のインスタンスによって呼び出すことができるため、コードのOPTimizationは実行されません(明らかに)。

コンパイラの最適化手法はヒューリスティックに基づいているため、このケースはミスだが、誰かが最も希少なケースを考えるだろう。

Javaの神からのコメントが待っている... :)

コンパイラがこれを最適化していないことを示す生存証明があります。ラベル5を確認してください:

public static void main(java.lang.String[]);
Code:
 Stack=2, Locals=2, Args_size=1
0:  bipush  100
2:  istore_1
3:  bipush  100
5:  lookupswitch{ //2
    200: 32;
    300: 40;
    default: 48 }
32: getstatic   #16; //Field java/lang/System.out:Ljava/io/PrintStream;
35: ldc #22; //String 200
37: invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
40: getstatic   #16; //Field java/lang/System.out:Ljava/io/PrintStream;
43: ldc #30; //String 300
45: invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
48: return
  LineNumberTable: 
line 11: 0
line 15: 3
line 17: 32
line 18: 40
line 21: 48

LocalVariableTable: 
Start  Length  Slot  Name   Signature
0      49      0    args       [Ljava/lang/String;
3      46      1    selection       I

StackMapTable: number_of_entries = 3
 frame_type = 252 /* append */
 offset_delta = 32
 locals = [ int ]
  frame_type = 7 /* same */
 frame_type = 7 /* same */


 }





Related