3

I'm indebted to this answer for the idea.

The following code compiles, but certainly shouldn't. It uses the value of x before it's been initialised. If you remove the StaticAssign. qualifier then it no longer compiles.

public class StaticAssign {

    public static final int x;

    static {
        System.out.println(StaticAssign.x);
        x = 5;
    }

    public static void main(String[] args) {}

}

On my machine, this consistently prints 0. If I change the type of x to String, it consistently prints null.

The question is: will it definitely print 0 or null, or might it access uninitialised memory and print out something else?

And even if this code gets through the compiler, why isn't it picked up by the JVM?

Is there a way to do nasty things based on this?

Community
  • 1
  • 1
chiastic-security
  • 20,430
  • 4
  • 39
  • 67

2 Answers2

2

It actually has been initialized. Variables in the global scope are initialized automatically. Variables of Object type will be initialized to null primitive like int will be initialized to 0. A variable declared not in the global scope must be initialized ie. declared in a method. Another problem is declaring it as final this is telling the compiler it must be explicitly initialized. So by adding the x=5 you are bypassing the compiler error saying it must be explicitly initialized. When you access it before this line at run-time it is initialized to 0 like any other primitive int type variable in the global scope.

brso05
  • 13,142
  • 2
  • 21
  • 40
  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/67029/discussion-on-answer-by-brso05-accessing-an-uninitialised-static-field-in-java). – Taryn Dec 16 '14 at 15:43
0

This is due to the way in which the classes are loaded.

First the class StaticAssign definition is loaded and the fields are initialized to default values:

StaticAssign.x = 0;

Then the initalization block is executed.

System.out.println(StaticAssign.x);
x = 5;

There is a reference to StaticAssign.x, the current class. As recursive initialization attempts are simply ignored, value of x is still 0.

This means that:

System.out.println(StaticAssign.x)

is valid because StaticAssign.x is a reference to field of an allready loaded class.

But if yo do:

System.out.println(x)   

then x is a reference to a final uninitalized field.

On the other hand, you never will access uninitialised memory. When the class definition is loaded variables are initialized to default values, before the initalization block is executed.

EDIT: There is a nice video "Elvis Lives Again" from Java Puzzlers that shows this much more better than I can explain

Tobías
  • 6,142
  • 4
  • 36
  • 62
  • Why x = 5 is legal but StaticAssign.x = 5 creates a compile error? Furthermore, if you print the value of StaticAssign.x before and after the x = 5 initialization, you get the values 0 and 5 but you can't use StaticAssign.x = 5 to make the assignment – David SN Dec 16 '14 at 15:29