Why variables must be final in anonymous methods, and class fields are not

If I had this anonymous method, I have to declare the x variable as final.

private void testMethod (ListField<BeanModel> listField){ final ListLoader<BeanModel> loader = new PagedListLoader<BeanModel>(); listField.addListener(Events.Attach, new Listener<ListViewEvent<BeanModel>>() { @Override public void handleEvent(ListViewEvent<BeanModel> be) { loader.load(); } }); } 

However, if loader was a class field, there is no need to declare it as final:

 public class testClass{ private ListLoader<BeanModel> loader = new PagedListLoader<BeanModel>(); private void testMethod (ListField<BeanModel> listField){ listField.addListener(Events.Attach, new Listener<ListViewEvent<BeanModel>>() { @Override public void handleEvent(ListViewEvent<BeanModel> be) { loader.load(); } }); //Could I modify loader reference here, before the method executes? //loader = null; } } 

Does anyone know the reason why they guarantee that local variables will not change when they are accessed, but do not do this for class fields?

+4
source share
4 answers

A local variable is allocated on the stack, and after testMethod() it will drop out of scope. Creating the final variable ensures that you can simply pass the reference to the anonymous class. If this was not final, a later assignment to it in testMethod() might change the value later with confusing results. (The user can expect a later assigned value to be used, but that would not be possible).

The field of the parent class, however, can be obtained through the parent link of the anonymous class, so any subsequent assignments can be processed without confusion.

+3
source

Inclusion in java docs

An anonymous class has access to members of the incoming class.
An anonymous class cannot access local variables in its scope that are not declared final or actually final (actually final means that the variable never changes after it is initialized). Method parameters are often actually final.)

The reason for this limitation becomes apparent if we shed light on how local classes are implemented. An anonymous local class can use local variables because the compiler automatically provides the class with a private instance field to store a copy of each local variable used by the class. The compiler also adds hidden parameters to each constructor to initialize these automatically created private fields. Thus, a local class does not actually refer to local variables, but simply to its personal copies. The only way this can work correctly is to declare local variables final so that they do not change. Given this guarantee, the local class is confident that its internal copies of the variables accurately reflect the actual local variables.

+8
source

Take a look at Lambdas and Conjures in java.

An anonymous inner class does not have information about this - you must indicate that it is final so that you can guarantee its existence.

This may be due to the nature of ListLoader , but I am not familiar with using this library.

Hope I pointed you in the right direction.

+1
source

Anonymous classes get local variables implicitly through constructors. That is, they get copies of the local wars that they use. Therefore, if we change the value of a variable in the main code, the anonymous class will not see this change. Declaring local vars finals helps to avoid this ambiguity.

+1
source

Source: https://habr.com/ru/post/1497007/


All Articles