3

When I use a non final variable from an inner class, I have a compile error :

public static void main(String[] args) {
    String s = "hello";
    s += "world";
    Object myObj = new Object() {
        public String toString() {
            return s; // compile error
        }
    };
    System.out.println(myObj);
}

However, I can fix this by adding a dummy final variable tmp that references the other variable I would like to access :

public static void main(String[] args) {
    String s = "hello";
    s += "world";
    final String tmp = s;
    Object myObj = new Object() {
        public String toString() {
            return tmp; // that works!
        }
    };
    System.out.println(myObj);
}

This process of adding a temporary final variable could be easily automatized, by a compiler for example.

My question is : why does the compiler do not perform automatically that simple change that allows us to get rid of this error ?

Arnaud
  • 7,259
  • 10
  • 50
  • 71
  • 1
    I believe this is fixed in Java 8. Can't wait... – Obicere Jan 29 '14 at 03:54
  • @Makoto not duplicate. The guy ask the technical reason why he has this error. I am asking why the compiler does not automatically fix it, because it _can_ be automatically fixed. – Arnaud Jan 29 '14 at 03:59
  • 2
    @SuperChafouin The answer does explain that though. – Sotirios Delimanolis Jan 29 '14 at 04:00
  • I had an answer to it (which was essentially "because Java said so"), but I was **very** dissatisfied with it; I did a bit of searching around and I feel that the question I referred to does answer the "why it's not automatically fixed" bit. – Makoto Jan 29 '14 at 04:01
  • Make sure to read the comments for the main answer too. – vanza Jan 29 '14 at 04:02
  • Very disappointed with the "duplicate" stuff. I can't see any answer to my question in the other one. – Arnaud Jan 29 '14 at 04:06
  • Well...I'm willing to bet that the technical reason why and the reason that the compiler can't fix the error are one and the same: there's a technical limitation that's preventing it. I did find a few other questions that ask something similar to this; I would encourage you to look around a bit and see if they satisfy your answer. If they really *don't*, then I don't mind casting a reopen vote. [Here's an example.](http://stackoverflow.com/a/4732617/1079354) – Makoto Jan 29 '14 at 04:08
  • The compiler _could_ quite easily fix it ! We could write a program that would go through the code and add a temporary static variable whenever it sees a reference to a non static variable. – Arnaud Jan 29 '14 at 04:11
  • Voted to reopen because I don't see an answer at the 'duplicate' that explains this. Crucially the accepted answer over there states itself that it is wrong (and it is wrong--how interesting). @Makoto That second question has a much better answer if this question is a duplicate of something. – Radiodef Jan 29 '14 at 04:13
  • Hey - all I'm providing is the, "it's not working and here's why", not the "let's go out and fix this issue". And yes @Radiodef; in hindsight the second link is far better. It'd probably be better to reopen and close as a duplicate of that, instead. – Makoto Jan 29 '14 at 04:14
  • Discussing why the compiler doesn't do it is kinda pointless. It just doesn't. Could it? Yes. But it doesn't. Because they forgot. Or were too lazy. Or wanted people to understand why this requirement exists. Ask Gosling. – vanza Jan 29 '14 at 04:18
  • 5
    The essence of the true answer is what @JonSkeet says: that the values are copied to fields within the anonymous class via an autogenerated constructor. There's no way for them to be changed in local scope after the class is declared so Java has made it a requirement they be final to (I guess) dispel any illusion they *could* be changed. – Radiodef Jan 29 '14 at 04:20
  • @Radiodef Ok, that makes perfect sense. Thanks for this answer. – Arnaud Jan 29 '14 at 04:21
  • 2
    @Obicere: Java 8 will allow you to not have the final keyword. But if the variable is not effectively final (i.e. you reassign new values to it, as it's done in the question), then it still won't compile. – JB Nizet Jan 29 '14 at 08:16
  • 2
    To be honest: if the code won't compile when reassigning a new value to the then non-final variable, I'd prefer the old way where the compiler enforces the final keyword. – chzbrgla Jan 29 '14 at 09:55

1 Answers1

0

Compiler can't replace all references to local variable with a constant but when the instance of inner class is constructed, the value is passed to appropriate constructor and stored in variable. According to need, It is cumbersome to automatically implement it.