[英]Class fields and final variables
據我所知,匿名內部類中的內部方法可以使用最終變量或類字段。 它們之間有顯着差異嗎? 例如:
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),則將發生相同的行為。 基於此,我得出結論,類字段和最終變量基本上是相同的(我是說它們在字節碼中表示相同),並且僅在范圍和分配值的可能性上有所不同。 我對嗎?
(我的意思是它們在字節碼中均等地表示)
讓我們找出答案。 拿這個代碼
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$000
在Example
。 因此,否-它們在字節碼中的表示方式不同。
最終變量仍然是變量。 不同之處在於,您只能分配一次值。 否則它們的行為相同。 字段也可以是最終字段(盡管那時它稱為常量),但其范圍保持不變。
final
關鍵字也稱為“修飾符”,因為它修飾成員的行為,而不是將其完全轉變為其他事物。
請記住,您仍然可以更改最終變量指向的對象。 根據您的情況,您可以修改數組,盡管變量是final。 您不能做的就是為變量分配另一個數組。
final
是指常量變量。 您不能更改常量的值。 但是您可以更改非最終成員變量的值
通過Outer.this
引用外部類中的字段,該字段實際上是final
local。 因此,從某種意義上說,並沒有什么區別。 顯然, final
僅對變量有意義,而對它所指向的對象沒有意義。
想象一下,如果將外部this
復制到封閉方法中的本地final
字段中。
final Outer outer = this;
testButton1.setOnClickListener(new View.OnClickListener() {
在匿名內部類中, outer
行為與outer
Outer.this
相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.