Hello.

In Java, a newbie is not the first time facing this situation, so please do not kick too much)).

The essence of what: There is a "main code" of the program. In which the variable is declared

int N = 0; 

Then, by necessity, I wanted to make a click handler on the button in this "main code" of the program.

Here I am writing (for example):

 button.addClickHandler (new ClickHandler(){ @Override public void onClick(ClickEvent event){ .... } }); 

and inside the handler I want to assign a value to the variable N (well, after all, it happens what is necessary ?!):

 button.addClickHandler (new ClickHandler(){ @Override public void onClick(ClickEvent event){ N = 123; } }); 

Does not give! Underlines N with red and an error saying that it is impossible to associate a value with this variable.

Announcement N through final does not save the situation.

Please explain how smart people solve this problem? Thank you in advance

  • They write on Sharpe))) - Qwertiy
  • You can code class (classes) where N and from where you are trying to get it - Leonid Lunin

2 answers 2

The visibility of variables / classes is determined by access modifiers (private, public etc), as well as the scopes inside the code blocks delimited by curly brackets {}

In the case of the latter, a variable declared in a block of code, surrounded by {} is visible only inside this block (except for the cases when it is a class variable that has public or default (that is, without modifying the modifier; is visible in one package) ) and all internal blocks.

Most likely, in your case, you have your variable N declared inside the -l method and, therefore, is not visible outside it, in other class methods. To make this variable available in all methods of a class, you need to put it in a block of code containing all the methods of the class, i.e. into the class itself.

Sample code:

 public class Test { int N = 1; //переменная уровня класса (поле класса); Видна во всех вложенных блоках кода, т.е. во всех методах класса public void someMethod() { int N2 = 1; } public void anotherMethod() { //N2 = 1; //ошибка компиляции - переменная N1 не видна из этого блока кода N = 2; //можно, т.к. переменнная объявлена в обрамляющем блоке кода и её тут видно } } 
  • Speech about the variable in the closure. You declare a local variable inside a block (not a class) and inside it some other function. The access to the variable will be readable, and Java will not allow writing. button.addClickHandler (new ClickHandler(){ in question button.addClickHandler (new ClickHandler(){ . - Qwertiy
  • So what is it about. Reading without problems. A record in the N does not. By the way, N is declared in the same public class method. And in the same method there is a click handler. And there are no problems with visibility. With the recording of the problem. - Vard32
  • @ Vard32, if your variable is a class field, then writing to it should without problems from anywhere in the class occur if it is not final ... - Yuriy SPb
  • @Qwertiy, well, yes, it won't come out of the local one - that's why I propose to transfer the variable to the class level - you can do anything with it) - Yuriy SPb 5:42 pm
  • Yes you are right. All right Just checked. - Vard32

Use instead of variable N field of some object. Java does not allow writing to variables accessible from the closure, since closure is done by value, not by reference.

This can not be done
http://ideone.com/4d8Seg

 import java.util.*; import java.lang.*; import java.io.*; import java.util.function.*; class Ideone { public static void main (String[] args) throws java.lang.Exception { int a = 9; Consumer<Integer> f = (Integer b) -> { System.out.println(a + b); // a = 3; // ERROR }; f.accept(10); // a = 3; // ERROR } } 

But like this, you can
http://ideone.com/CkyIuK

 import java.util.*; import java.lang.*; import java.io.*; import java.util.function.*; class Ideone { static class Wrapper { public Integer a; } public static void main (String[] args) throws java.lang.Exception { Wrapper w = new Wrapper(); wa = 9; Consumer<Integer> f = (Integer b) -> { System.out.println(wa + b); wa = 7; // Allowed }; f.accept(10); f.accept(10); wa = 3; // Allowed f.accept(10); } } 

Hmm ... Why can't the last assignment in the first example be made? .. 0_o

Because the closure in Java is done by value. The copy of the variable a falls into the function f scope. Naturally, changing the variable inside or outside f will not affect the second copy. Therefore, we decided that it is impossible to change the variable anywhere. That is, the variable must be final , but it is allowed not to write, as long as it actually is immutable.

By the way, in C # this is solved by automatically placing the lockable variables in an intermediate object. Accordingly, any change in the fields of this object is visible in both places.

In C ++, you need to explicitly indicate whether the lambda will receive a value or a link. This approach is not applicable in Java and Sharpe, since the function may exist longer than the variable in the stack - in this case, the reference to the variable will become incorrect and this is not verifiable. In the pros, of course, the responsibility for such an action on the programmer.

  • Personally, I did not understand what you wanted to say ( - YuriySPb
  • one
    @YuriSPb, ideone.com/4d8Seg . - Qwertiy
  • This is understandable ... Apparently I need to find out what the beast is "closure") - YuriySPb
  • @ ЮрийСПб, added a response code. - Qwertiy
  • Hmm ... And why can't the last assignment in the first example be made? .. 0_o - YuriiSPb