3

In a school test I used non final variables inside an anonyme inner class. On the the school Computer and on my private Computer(using x86 jre1.8.0_45) it is working.

However, on the teachers Laptop Eclipse is showing errors (The variables should use final). He is using jre1.8.0.x version (don't know the exact version).

Any ideas why it is working on my computer and not on his computer?

In this code example the no final object jLabel is used inside the actionPerformed function of the ActionListener:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;

public class Main {
    public Main(String[] args) {
        JLabel jLabel = new JLabel();
        JButton button = new JButton();
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                jLabel.setText("xyz");

            }
        });
    }
}
Murli
  • 1,258
  • 9
  • 20
Rhias
  • 63
  • 5
  • 2
    Sounds strange, should be either a field variable or declared final as far as I can tell – cYrixmorten Dec 07 '15 at 14:52
  • Is it a warning or error ? – Abhiram mishra Dec 07 '15 at 14:52
  • 2
    Possible duplicate of [Java stopped erroring on non-final variables in inner classes (java 8)](http://stackoverflow.com/questions/28408109/java-stopped-erroring-on-non-final-variables-in-inner-classes-java-8) – azurefrog Dec 07 '15 at 14:54
  • 2
    Sounds like he has eclipse configured to target(compile to) java 1.7. This is possible even if you have java 1.8 installed because eclipse includes its own compiler – MTilsted Dec 07 '15 at 14:55

2 Answers2

6

Newer java versions are more tolerant in this concern: they only require that they should be "effectively final".

At the end, the difference is not soo big - you only can use variables which you COULD tag with final; you may not modify them.

If you are at that place, you as well can make them "really" final, and it works everywhere.

BTW, on 1.8 with its new lambda syntax you can write more elegantly

button.addActionListener((ActionEvent arg0) -> jLabel.setText("xyz"));
glglgl
  • 89,107
  • 13
  • 149
  • 217
  • More specifically "effectively final" was introduced from Java 1.8... On previous versions it has to be **declared** as final. – Codebender Dec 07 '15 at 14:56
  • @Codebender I thought so as well, but the OP seems to observe this "old" behaviour on 1.8 versions as well - if he is not wrong... – glglgl Dec 07 '15 at 14:57
  • "Newer" is relative. 7 and older are EoPU, obsolete and should not be used anymore. – Grim Dec 07 '15 at 15:00
0

You could define the Listener not as an anonymous class but as a private inner class in order to avoid that problem:

public class Main {

    public Main(String[] args) {

        JLabel jLabel = new JLabel();
        JButton button = new JButton();
        button.addActionListener(new MyActionListener(jLabel));
    }

    private class MyActionListener implements ActionListener {

        private JLabel jLabel;
        MyActionListener(JLabel jLabel) {
            this.jLabel = jLabel;
        }

        @Override
        public void actionPerformed(ActionEvent arg0) {
            jLabel.setText("xyz");            
        }

    }
}

This way you can just pass the label (and button if you need) to the constructor of the listener and will be able to use it without any problems.

ParkerHalo
  • 4,341
  • 9
  • 29
  • 51