Mohamad Alhamoud
Mohamad Alhamoud

Reputation: 4929

What is the explanation of this results in Java?

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

Answers (5)

Matthew Flaschen
Matthew Flaschen

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.

  1. j is an instance field.
  2. i is an instance field.
  3. j is used on the right hand side.
  4. j is a simple name (basically, the field is used directly)
  5. Main is the inner-most class enclosing both.

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

ring bearer
ring bearer

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

Woot4Moo
Woot4Moo

Reputation: 24316

J wasn't declared before being referenced for assignment

Upvotes: 0

dty
dty

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

SLaks
SLaks

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

Related Questions