6

I have the following piece of code-

{s = "Hello";}
String s;

This compiles fine, implying that the variable definitions are executed before the instance blocks. However, if I use the following code instead, it does not compile ("error: illegal forward reference").

{s = "Hello"; String ss = s;}
String s;

So it is not possible to use the value of 's' on the right-hand side of a statement in an instance block that comes BEFORE the variable definition. Is there a sane explanation of what is happening behind the scenes, or is this simply an idiosyncratic feature of Java?

P.S. I have seen a similar question asked before, the only explanation given there is that it is a feature of Java. I am writing this to ask the community if that is indeed the final word on this question.

9
  • Whenever you find yourself writing "it does not compile," remember to include the specific error you're getting. I've added what I got when I did this with Java 8. Commented Sep 17, 2014 at 16:20
  • 1
    +1. Thanks for the first codes. I never knew that it compiles :) Commented Sep 17, 2014 at 16:25
  • Yeah, fascinating question. Commented Sep 17, 2014 at 16:26
  • @T.J.Crowder Is this a relevantly new addition to Java? It's not working on the IDEONE site. Commented Sep 17, 2014 at 16:32
  • 1
    @T.J.Crowder, Thanks for adding the compiler error. Commented Sep 17, 2014 at 17:07

3 Answers 3

3

JLS §8.3.3 ("Forward References During Field Initialization") sheds some light here:

Use of instance variables whose declarations appear textually after the use is sometimes restricted, even though these instance variables are in scope. Specifically, it is a compile-time error if all of the following are true:

  • The declaration of an instance variable in a class or interface C appears textually after a use of the instance variable;

  • The use is a simple name in either an instance variable initializer of C or an instance initializer of C;

  • The use is not on the left hand side of an assignment;

  • C is the innermost class or interface enclosing the use.

The first bullet would apply to your example.

As for the "why" part, "why" is usually a tricky question with language design, but in this case they helpfully added this note further down:

The restrictions above are designed to catch, at compile time, circular or otherwise malformed initializations.

Sign up to request clarification or add additional context in comments.

1 Comment

The best reason I can come up with 'why' is that the JVM can't guarantee that the required fields have been filled. Initializer blocks are executed before the fields are constructed, so trying to reference a field that isn't initialized is problematic. I could see this being a new feature in a newer Java version if it didn't have such a code smell. Beyond that, only person to really answer the question here: +1.
0

In second case you will get compilation error IllegalForwardReference due to the fact that usage of the variable s is not on the left hand side of an assignment and JLS explicitly states it as one of the reason to get IllegalForwardReference error

Comments

0

I just can tell you this: The compiler moves all the initialization code to the end of the constructors' body (repeating code for every constructor). Decompiling an example would show it off.

So, you must realise that, in this way, the declaration order of some variable matters when evaluating it as a right-hand side, even if it doesn't matter when evaluating it as a left-hand side.

One way to get rid off these incoherences is to pre-pend the scope "this" to every instance variable.

2 Comments

"The compiler moves all the initialization code to the end of the constructors' body" You mean the beginning, not the end.
@Little Santi, You pointed out an interesting thing. Indeed, if I pre-pend 'this' to 's' in 2nd code example, it does compile, just as you said. But I don't understand why.. this is even more confusing..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.