0

私の知る限り、匿名内部クラスの内部メソッドは最終変数またはクラス フィールドを使用できます。それらの間に大きな違いはありますか?例えば:

 final int[] intArr = new int[1];

Button testButton1 = (Button) findViewById(R.id.btnTest1);
testButton1.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
    intArr[0]++;
    Log.i("test", String.valueOf(intArr[0]));
  }
});

Button testButton2 = (Button) findViewById(R.id.btnTest2);
testButton2.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
    intArr[0]--;
    Log.i("test", String.valueOf(intArr[0]));
  }
});

2 つのボタンがあり、どちらもintArr[0]を使用し、値を取得および設定できます。intArr[0]をprivate int value;のようないくつかのクラス フィールドに置き換えた場合も、同じ動作になります。 これに基づいて、クラス フィールドと最終変数は基本的に同じ (つまり、バイトコードで同等に表現される) であり、スコープと値を割り当てる可能性のみが異なると結論付けます。私は正しいですか?

4

4 に答える 4

2

(つまり、それらはバイトコードで等しく表されます)

確認してみましょう。このコードを取る

class Example {

  private static int[] outside = new int[]{1};

  public static void main(String [] args){
    final int[] inside = new int[]{2};

    Object inner = new Object(){{
      System.out.println(outside[0]);
      System.out.println(inside[0]);
    }};
   }
  }

コンパイルして2つのクラスを取得し、これらを使用して逆アセンブルjavap -cします

class Example {
  Example();
    Code:
       0: aload_0       
       1: invokespecial #2                  // Method java/lang/Object."<init>":()V
       4: return   

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1      
       1: newarray       int
       3: dup           
       4: iconst_0      
       5: iconst_2      
       6: iastore       
       7: astore_1      
       8: new           #3                  // class Example$1
      11: dup
      12: aload_1       
      13: invokespecial #4                  // Method Example$1."<init>":([I)V
      16: astore_2      
      17: return        

  static int[] access$000();
    Code:
       0: getstatic     #1                  // Field outside:[I
       3: areturn       

  static {};
    Code:
       0: iconst_1      
       1: newarray       int
       3: dup           
       4: iconst_0      
       5: iconst_1      
       6: iastore       
       7: putstatic     #1                  // Field outside:[I
      10: return        
}

final class Example$1 {
  final int[] val$inside;

     Example$1(int[]);
        Code:
           0: aload_0       
           1: aload_1       
           2: putfield      #1                  // Field val$inside:[I
           5: aload_0       
           6: invokespecial #2                  // Method java/lang/Object."<init>":()V
           9: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
          12: invokestatic  #4                  // Method Example.access$000:()[I
          15: iconst_0      
          16: iaload        
          17: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
          20: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
          23: aload_0       
          24: getfield      #1                  // Field val$inside:[I
          27: iconst_0      
          28: iaload        
          29: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
          32: return        
    }

変数insideはクラス内のフィールドとして作成されますがExample$1、変数outsideは で自動生成されたメソッドを介してアクセスさaccess$000Exampleます。したがって、いいえ - それらはバイトコードで同等に表現されません。

于 2013-07-08T17:36:09.047 に答える
0

final定変数を参照します。定数の値は変更できません。ただし、非最終メンバー変数の値は変更できます

于 2013-07-08T16:32:34.773 に答える