6

Why when I use reference this in a variable declaration, illegal forward reference doesn't appear? What's the difference between declaration with this and without it?

The following example fails to compile because of the illegal forward reference:

class FailsToCompile {
    int a = b; //illegal forward reference
    int b = 10;
}

By qualifying the use of b by this the compilation error goes away.

class Compiles {
    int a = this.b; //that's ok
    int b = 10;
}
6
  • Possibly related (although it is about static field) Why illegal forward reference error not shown while using static variable with class name Commented May 2, 2019 at 9:43
  • 1
    @Pshemo I think the mechanics behind it are the same, aren't they? So that should count as a duplicate Commented May 2, 2019 at 9:44
  • 1
    @Lino You are probably right, but since I didn't read that post yet I don't want to use my dupe-hammer based just on probability. Commented May 2, 2019 at 9:46
  • 3
    Welcome to Stack Overflow! Please read "How to create a minimal reproducible example". Then use the edit link to improve your question (do not add more information via comments). Otherwise we are not able to answer your question and help you. Meaning: scope is extremely important here, and your code snippets leave out the scope completely! Commented May 2, 2019 at 9:48
  • I suggest (based on no solid evidence) that the prohibition on forward references is merely a best-effort attempt "to catch, at compile time, circular or otherwise malformed initializations". For example, you can also forward-reference a variable through a method invocation. So, it catches obviously-wrong code, but just doesn't try too hard to stop you if you are really going to insist you know what you're doing. Commented May 2, 2019 at 10:06

1 Answer 1

6

Assuming the following class

public class MyClass {
    int a = b;
    int b = 10;
}

The JLS 8.3.3. states in your case :

Use of instance variables whose declarations appear textually after the use is sometimes restricted
- The use is a simple name in either an instance variable initializer of C or an instance initializer of C

Now, using the member this allows you to access an instance that is already declared with default values ( a = 0, b = 0 ) but not yet fully initialized. This is visible if you check the result of:

public class MyClass {
    int a = this.b;
    int b = 10;
}

You would not get the expected value :

new MyClass().a //0
new MyClass().b //10

I can't explain why this is legal exactly since this would never give a correct value. We can find some explanation about why the restriction exist :

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

But why allowing this to works...


Knowing that during an initialization of an instance, the following actions occurs :

  1. Member declaration
  2. Block execution and Field initialization in order
  3. Constructor execution

Give some strange behavior:

public class MyClass {

    {
        b = 10;
    }
    int a = this.b;
    int b = 5;
    {
        b = 15;
    }

    public static void main(String[] args) {
        MyClass m = new MyClass();
        System.out.println(m.a); //10
        System.out.println(m.b); //15
    }
}

I would limit the initialization in the constructor.

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.