12

Is the following code the case of legal forward referencing? if yes why?

public class MyClass
{
  private static int x = getValue();
  private static int y = 5;
  private static int getValue()
  {
    return y;
  }
  public static void main(String[] args)
  {
    System.out.println(x);
  }
}
templatetypedef
  • 328,018
  • 92
  • 813
  • 992
Vibhor
  • 211
  • 3
  • 7

2 Answers2

19

The above code you have is perfectly legal Java. In Java, static fields are initialized as follows: first, all fields are set to the default for their type (0, false, or null), and then initialized in the order in which they are declared. This means that the above code is guaranteed to do the following:

  1. Set x and y to zero, since that's the default value for ints.
  2. Initialize x by calling getValue(), which reads the value of y. Since y hasn't yet been initialized, it still has the value 0.
  3. Initialize y to 5.

This means that x will take the value 0 and y will take the value 5. This behavior is portable and guaranteed. You can see this here.

Hope this helps!

templatetypedef
  • 328,018
  • 92
  • 813
  • 992
  • What would be the case if those were not Static variables and method? – Vibhor Apr 05 '12 at 21:05
  • 2
    I believe that the behavior is the same - the initialization is first setting everything to the default value, then initializing each with the specified value, then calling the constructor. – templatetypedef Apr 05 '12 at 21:06
  • 1
    Which, btw, is one reason you should never call a non-final (or private) method from a constructor; it's too easy for someone to override that method and see a not-yet-constructed `this`, even to the point of seeing an uninitialized final field. – yshavit Apr 05 '12 at 21:26
  • Doesn't your answer go against the answer below where you get a forward reference error with private static int x=y; private static int y=5; ? – Neil Walker Jan 29 '13 at 10:50
  • @user1186046- Java allows you to *indirectly* have one variable forward reference another, but doesn't let you *directly* have one variable forward-reference another. The OP's code doesn't directly set x equal to y, so there is no error. However, you are right that your version of the code will give a forward reference error. – templatetypedef Jan 29 '13 at 17:01
5

You can tell whether it's legal or not by the fact that it compiles; unlike some other languages, Java doesn't have the notion of "undefined behavior." What happens here is completely spelled out. It may be counterintuitive, but it's specifically legal: you can access a static variable before it's initialized from a method called while initializing another static variable. The superficially similar case of accessing y directly from x's initializer -- i.e.,

private static int x = y;
private static int y = 5;

is specifically disallowed. There's really no strong reason why -- it's just how it is.

Ernest Friedman-Hill
  • 77,245
  • 10
  • 138
  • 182
  • What if the variables are non static..is the behavior same in that case too? – Vibhor Apr 05 '12 at 21:09
  • Yes, it's effectively the same. The rules listed for statics are very slightly different because there are no actual "constructors" for a class, but objects are initialized in essentially the same way. For instance variables, initializers and instance blocks are prepended, in order of appearance, to each constructor. For statics, initializers and static blocks are compiled, in order, into a single method named `()` . – Ernest Friedman-Hill Apr 05 '12 at 21:15
  • Having a program that can be tested with a compiler is a luxury when it comes to questions like this I'm afraid. This is taken from a mock exam for OCJP exam. I'm learning it now, and it's these stupid questions that are completely pointless that make a mockery of the intent for the exam. – Neil Walker Jan 29 '13 at 10:52