簡體   English   中英

類字段和最終變量

[英]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$000Example 因此,否-它們在字節碼中的表示方式不同。

最終變量仍然是變量。 不同之處在於,您只能分配一次值。 否則它們的行為相同。 字段也可以是最終字段(盡管那時它稱為常量),但其范圍保持不變。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM