Reputation: 4929
I have the following code :
public class Main {
private int i = j; //1
private int j = 10;
public static void main(String[] args) {
System.out.println((new Main()).i);
}
}
and there is a compiler error in line 1 because an illegal
forward reference.
But when I am trying the following code :
public class Main {
int i = getJ(); //1
int getJ(){
return j;
}
int j=10;
public static void main(String[] args) {
System.out.println(new Main().i);
}
}
it works fine and the result is 0.
Why there is no illegal
forward reference in line 1 here?.The two codes look similar to me.
Upvotes: 1
Views: 226
Reputation: 284786
That rule only applies to fields. Specifically (JLS 8.3.2.3):
The declaration of a member needs to appear textually before it is used only if the member is an instance (respectively static) field of a class or interface C and all of the following conditions hold:
- The usage occurs in an instance (respectively static) variable initializer of C or in an instance (respectively static) initializer of C.
- The usage is not on the left hand side of an assignment.
- The usage is via a simple name.
- C is the innermost class or interface enclosing the usage.
All of the conditions hold for the first example.
At least one ("usage is via a simple name") does not apply for the second example. Basically, the compiler tries to catch circular errors like:
int i = j + 1;
int j = i + 1;
It's somewhat over-cautious, but it mostly works. Before j = 10 is executed, j is still 0, so that's the value i is set to. There's no way to extend your getJ example to create a loop (of course, there are other ways to create infinite recursion at runtime).
Upvotes: 4
Reputation: 20773
Java runtime has information that you have an instance variable, which is int, called "j" however, the value is not set to 10 until the bytecode interpreter reaches the initialization.
That is the reason you are seeing default int value as return value.
Upvotes: 2
Reputation: 18998
Because you are explicitly calling a method and accessing a member variable before the instance initialisation is completed. There's a limit to how much the compiler can prevent you from doing stupid things! :-)
Upvotes: 2
Reputation: 887195
Methods can be used before they are declared.
private int j = 10;
is an executable statement that must be executed at some point in time. Therefore, the ordering of field declarations is meaningful.
A method declaration is not itself executable.
Therefore, the ordering of method is completely meaningless.
Upvotes: 6