0

I wrote some code and everything worked fine, but when I open the same code on another computer, I get the following errors:

Cannot refer to the non-final local variable usernameTextField defined in an enclosing scope
Cannot refer to the non-final local variable portTextField defined in an enclosing scope
Cannot refer to the non-final local variable usernameTextField defined in an enclosing scope
Cannot refer to the non-final local variable portTextField defined in an enclosing scope

The code that gives this error:

private static GridPane initGUI(){
    GridPane root = new GridPane();
    TextField usernameTextField = new TextField();
    TextField portTextField = new TextField();
    Button button = new Button("Login!");
    root.add(new Label("Username:"),0,0);
    root.add(new Label("Port:"),0,1);
    root.add(usernameTextField,1,0);
    root.add(portTextField,1,1);
    root.add(button, 0, 2);

    /* Button action */
    button.setOnAction(new EventHandler<ActionEvent>(){
        @Override
        public void handle(ActionEvent event) {
            boolean portCorrect = true;
            String username = usernameTextField.getText();
            int port = 0;

            /* Try casting to integer*/
            try{
                port = Integer.parseInt(portTextField.getText());
            }catch(NumberFormatException e){
                portCorrect = false;
            }

            /* Invalid username or port*/
            if(username.length() < 1 && portCorrect){
                usernameTextField.clear();
                portTextField.clear();
            }
        }

    });
    return root;
}

I've looked for a solution for my problem and have found many of them that are alike, but the given solutions never solve my problem.

EDIT: using Java8

EDIT2: I appreciate the answers, but those were the answers I found by googling the problem. They don't really solve the problem. The code I pasted here works fine on every computer I ran it on and on the computer of my project partner, but not on mine. Changing the objects to final works, but isn't really what I'm looking for.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Dario De Mits
  • 5
  • 1
  • 1
  • 3
  • Are you using Java 7 or 8? – assylias Mar 31 '16 at 13:56
  • If Java doesnt support encolures, why does it work on another computer? – Dario De Mits Mar 31 '16 at 14:04
  • 3
    I understand your confusion, @DarioDeMits, but the answers are correct. The variables need to be final (or effectively final in Java 8) in order to reference them like that. Since they work elsewhere, that computer must be Java 8. Since they don't work on the new machine, either a) it's not Java 8, or b) you're compiling it _for_ Java 7 or lower (but still using the Java 8 compiler), or c) some other weird thing. That's all there is. Java didn't suddenly just change, and only on one machine. – Erick G. Hagstrom Mar 31 '16 at 14:18
  • You could always just implement EventHandler in a non-anonymous class, or implement it in the UI class itself, rather than going with the non-anonymous approach. If you're running this on a Java 8 VM, then you're going to hit the "sufficiently final" snag regarding outer access of variables. The difference is in VM. How you choose to manage that appropriately in your code is up to you given the supplied answers. – ManoDestra Mar 31 '16 at 14:29
  • So if I am understanding it corretly, Java 7 will force you to make the objects final, but Java 8 will make the objects final for you without you knowing it? There must be something weird happening in my eclipse then, because I'm compiling it for Java 8. – Dario De Mits Mar 31 '16 at 14:30
  • Eclipse. Ok, good. Java project, or plug-in project? – Erick G. Hagstrom Mar 31 '16 at 15:08
  • Please check your Java Compiler preferences. You may have your compiler compliance level set to something less than 1.8. I was able to reproduce your problem by playing with that. – Erick G. Hagstrom Mar 31 '16 at 15:13
  • 2
    BTW, Java 8 doesn't "make objects final for you", it just recognizes when they don't get reassigned. They are "effectively final" because, after the point at which you reference them, their values will never change. – Erick G. Hagstrom Mar 31 '16 at 15:15

2 Answers2

5

Probably you are using java 8 and the other computer is using java 7. Java requires references to variables from inner classes to be final variables. Java 8 will make them effectively final if you don't reassign.

Add final to:

final GridPane root = new GridPane();
final TextField usernameTextField = new TextField();
final TextField portTextField = new TextField();
final Button button = new Button("Login!");
Liviu Stirb
  • 5,876
  • 3
  • 35
  • 40
  • This isn't really the answer I'm looking for. The weird thing is that the code I pasted here works on every computer I tried it on except on mine (see edit in original post). – Dario De Mits Mar 31 '16 at 14:19
  • 1
    @DarioDeMits try javac -version on your computer and let me know what it displays. – Liviu Stirb Mar 31 '16 at 14:30
2

You can't use the variables in the anonymous class (new EventHandler(){...}), that are not marked as final or a filed on the enclosing class. So in your case, the easiest solution would be to make the variables final

...
final TextField usernameTextField = new TextField();
final TextField portTextField = new TextField();
...
Jiri Kremser
  • 12,471
  • 7
  • 45
  • 72