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]并且可以获取和设置它的值。如果我用一些类字段(如私有 int 值)替换intArr[0] ,也会出现相同的行为; 基于此,我得出结论,类字段和最终变量基本相同(我的意思是它们在字节码中的表示相同)并且仅在范围和赋值的可能性上有所不同。我对吗?

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

编译它以获得两个类,然后将它们反汇编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 回答
1

最终变量仍然是变量。不同之处在于您只能分配一次值。否则,它们的行为相同。一个字段也可以是最终的(虽然它被称为常量),它的范围保持不变。

关键字也称为“final修饰符”,因为它修改成员的行为,而不是把它变成完全不同的东西。

请记住,您仍然可以更改最终变量指向的对象。在您的情况下,尽管变量是最终的,但您可以修改数组。你不能做的是为你的变量分配另一个数组。

于 2013-07-08T16:34:08.817 回答
0

外部类中的字段通过 引用Outer.this,这实际上是final本地的。所以在某种程度上,并没有真正的区别。显然,final只对变量有意义,对它指向的对象没有意义。

想象一下,如果您将外部复制this到封闭方法中的本地final字段。

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

outerOuter.this行为与匿名内部类中的行为相同。

于 2013-07-08T16:39:32.380 回答
0

final指常量变量。你不能改变常量的值。但是你可以改变非最终成员变量的值

于 2013-07-08T16:32:34.773 回答