简体   繁体   中英

Java local variable accessed from within inner class; needs to be declared final, why it works in NetBeans?

In my Java app, there is a method and it has the following code:

JButton Button = new JButton(Content);
Button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
        doSomething(Button.getText());
    }
});

It compiles and works fine from NetBeans 8.1, but today when I tried to compile the project from command line, it gave me the following error:

local variable Button is accessed from within inner class; needs to be declared final

My question is: why the same code complies and works fine from NetBeans 8.1 but can't compile in command line?

My command line Java version is: 1.8.0_77

And my NetBeans Java version is: 1.8.0_65

That shouldn't matter, so why NetBeans doesn't consider it an error?

Edit : Woo, BIG SURPRISE for me, I just did a check on javac :

C:\\Users\\USER>java -version java version "1.8.0_77"

C:\\Users\\USER>javac -version javac 1.7.0_40

Wait a minute, I'm 100% confused big time, first I never knew there is a "javac -version" command, I thought "java -verison" will tell me both java and javac, and I assume they are the same, second, when I installed Java, I thought the installer will update it automatically, and javac is part of java, so it should be internally consistent, but it definitely is NOT, so how can my java -version being different from my javac -version ? In other words how can I trust Oracle to install my java and javac at the same time, if it doesn't do the job, does that mean everytime I update Java, I need to somehow install my javac by hand ? I've never done that, so why and how could this happen ?

Prior to Java 8, all local variables that need to be accessed in an inner class need to be declared final . This is due to an implementation detail -- local variables are implemented as hidden instance variables of the inner class. If the variable could be changed, then the copy in the inner class would be incorrect.

In Java 8, this requirement was relaxed to "final" or "effectively final" (scroll down about 2/3 of the way).

However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final . A variable or parameter whose value is never changed after it is initialized is effectively final.

The variable doesn't have to be declared explicitly to be final , it just has to be effectively final -- not explicitly final , just not changed.

You are not changing Button , so it's effectively final and it compiles under Java 8. However, Java 7 still required it to be declared explicitly final so there is a compiler error.

Fix your path so that javac is your Java 8 installation. It's possible you have a JRE (no "javac" executable) that is Java 8 but a JDK 1.7 (Java 7) installation, which could explain your versioning output. In that case you would need to download and install the Java 8 JDK (1.8).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM