0

As far as I know to inside methods in anonymous inner class can use final varibles or class fields. Is there a significant difference between them? for example:

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

I have 2 buttons and both them use intArr[0] and can get and set it value. The same behavior will be if I replace intArr[0] with some class fields like private int value; Based on this, I conclude that class fields and final variables are basically the same (I mean they are represented equally in the bytecode) and have difference only in scope and and the possibility to assign a value. Am I right?

4 Answers 4

2

(I mean they are represented equally in the bytecode)

Let's find out. Take this code

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

Compile it to get two classes and then disassemble these using javap -c to get

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        
}

and

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        
    }

We see that the variable inside is created as a field inside the class Example$1 whereas the variable outside is accessed via an automatically generated method access$000 in Example. Therefore no - they are not represented equally in bytecode.

Sign up to request clarification or add additional context in comments.

Comments

1

A final variable is still a variable. The difference is that you can assign a value only once. Otherwise they behave the same. A field can also be final (although it is called a constant then), it's scope stays the same.

The final keyword is also called a "modifier" because it modifies the behaviour of a member rather then turning it into something entirely else.

Keep in mind that you can still change the objects a final variable points to. In your case you can modify the array although the variable is final. What you can't do is assign another array to your variable.

Comments

0

final referes to the constant variables. you cannot change the value of constants. But you can change the value of non final member variables

1 Comment

Assuming OP referring object, I would rephrase answer saying, final variables references can't be modified (can't point to another object), but object state can be changed.
0

A field in the outer class is referenced through Outer.this, which is effectively a final local. So in a way, there isn't really a difference. Obviously, final only has meaning for the variable, not the object it points to.

Imagine if you copied the outer this to a local final field in the enclosing method.

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

outer behaves the same as Outer.this within the anonymous inner class.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.