First off, I apologise if this is a duplicate question. I found many similar ones, but none that directly address my question.
In preparation for an upcoming exam, I am doing a past paper. It has a question that gives a code snippet. We have to state if it compiles, and if not, write the line at which the first compiler error occurs and explain it. This is the snippet:
public static void main(String[] args) {
JFrame f = new JFrame("hi");
JTextField jtf = new JTextField(50);
jtf.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent evt) {
jtf.setText(evt.getLocationOnScreen().toString());
}
});
f.add(jtf);
f.setVisible(true);
}
I was expecting it not to compile as jtf
is not final
. I tested my theory by entering the code above in Eclipse, which flagged the expected error, but compiled and ran just fine. It was only after mousing over the JTextField
that I got the expected error:
java.lang.Error: Unresolved compilation problem: Cannot refer to the non-final local variable jtf defined in an enclosing scope
I did a bit of searching, and discovered that Eclipse uses its own version of the Java compiler. So I remade the file outside of Eclipse and compiled/ran it via the command line. It compiled with no errors or warnings, and when mousing over the text field, displayed the desired java.awt.Point[x=...,y=...]
.
My understanding of anonymous inner classes is that they can access:
- Fields of the enclosing class
- Methods of the enclosing class
- Local variables of the enclosing scope, provided they are
final
So what am I missing? According to what I know, this code should not work.
I guess you are compiling with Java 8. Here your
jtf
variable is effectively final, so it compiles fine. A variable is effectively final if its value is never changed after you initialized it.See also Local Classes:
and
Accessing Local Variables of the Enclosing Scope, and Declaring and Accessing Members of the Anonymous Class
If you tried with:
you'll have your expected error.
So the answer of the exam question is: it compiles only if you're using Java 8+.
Java 8 added the ability to access "effectively final" variables. The
final
keyword is no longer required as long as a variable is never changed after it is initialized.It may work in
Java8
as the stress is onEffectively Final
which means once the value is assigned tojtf
it should not be changed after wards. As per Java doc:Seems that your Eclipse IDE uses Java 7 compiler. To change this to Java 8 use Project->Properties->Java Compiler->Compiler compliance level.