2013-07-08 46 views
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; 基於此,我得出結論:類字段和最終變量基本相同(我的意思是它們在字節碼中被等同表示),並且僅在範圍內有區別,並且有可能分配一個值。 我對不對?

回答

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

編譯得到兩班,然後拆開這些使用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。因此,不 - 它們在字節碼中沒有相同的表示。

+0

哇,至於我 - 很好的答案 – anber

0

final參照常數變量。你不能改變常量的值。但是,您可以更改非最終成員變量的值

+5

假設OP引用對象,我會重新回答說,最終變量引用不能被修改(不能指向另一個對象),但對象狀態可以改變。 – kosa

1

最終變量仍然是一個變量。區別在於您只能分配一次值。否則,他們的行爲是一樣的。一個字段也可以是最終的(儘管它現在被稱爲常量),它的作用域保持不變。

final關鍵字也被稱爲「修飾符」,因爲它修改成員的行爲,而不是將其轉化爲其他東西。

請記住,您仍然可以更改最終變量指向的對象。在你的情況下,你可以修改數組,儘管變量是最終的。你不能做的是將另一個數組分配給你的變量。

0

外部類中的字段通過Outer.this引用,該字段實際上是本地的final。所以從某種意義上說,沒有什麼區別。顯然,final只對變量有意義,而不是它指向的對象。

想象一下,如果您將外部this複製到封閉方法中的本地final字段中。

final Outer outer = this; 
testButton1.setOnClickListener(new View.OnClickListener() { 

outer行爲一樣的匿名內部類內Outer.this