Search code examples
javastaticfinal

How are static final and static members handled in Java?


I have already seen a few things about static variables here on Stack Overflow and elsewhere on the web. However the answers aren't clear to me. When I think I found the answer, some other source contradicts the statement (or at least, I think it does).

For example: m0bius tells us in How does the static keyword work in Java? (in the section "When is this copy [ed. the static variable] created?") that static variables are created at run time. But if I check https://en.wikipedia.org/wiki/Class_variable (section "Static member variables and static member functions") it tells me the opposite occurs in some languages and the same happens in other languages.

My question here can be separated into two different questions:

  • In Java, are static variables of a class created at run time or at compile time?
  • In Java, are final static variables of a class created at run time or at compile time?

What I mean with compile time versus run time:

  • compile time: when the source code is compiled (so when the .class-file is created)
  • run time: when the program is actually running

Some code only used for the purpose of this question:

// MyClass.java
public class MyClass {
    public static int instances;
    public final static double PI = 3.14159265359

    public MyClass() {
        instances++;
    }
    // ...
}

// Main.java ; version 1
public class Main {
    public static void main(String args[]) {
        System.out.println("I am doing nothing with MyClass");
    }
}
// OUTPUT: I am doing nothing with MyClass

// Main.java ; version 2
public class Main {
    public static void main(String args[]) {
        System.out.println("PI = " + MyClass.PI);
        MyClass obj1 = new MyClass();
        MyClass obj2 = new MyClass();
        System.out.println("instances = " + MyClass.instances);
    }
}
OUTPUT:
3.14159265359
2

If both static and final static variables would be created at run time, in the Main's first version neither of both static variables (instances and PI) of class MyClass would be created. But I would kind of expect that the final static variable PI would be created at compile time (so it would be "embedded" in the .class-file) because I think this would have a better performance (no matter what happens with the class MyClass, PI will always be 3.14159265359 so it might as well be put in the binary file).
This could be the same with the static variable, but it might change throughout the program.


Solution

  • In Java, are static variables of a class created at run time or at compile time?

    No variables are "created" at compile time in Java, if by created you mean allocated and initialized. They are all created at runtime. Whether or not they are static or static final has no bearing on when they get allocated.

    But I would kind of expect that the final static variable PI would be created at compile time (so it would be "embedded" in the .class-file) because I think this would have a better performance...

    That's not how it works in Java. When class files are "compiled" they really are mostly being encoded. There certainly is some work that is done but a super-large percentage of the what we think of compilation (in terms of languages like C) is happening at runtime. This is especially true when we look at optimizations and inlining.

    The compiler does do some pre-work such as being able to pre-calculate the values of fields (static or instance) ahead of time if possible. For example, if you define your field like the following, then the multiplications will be done at compilation time:

    private long timeoutMillis = 10 * 24 * 3600 * 1000;
    

    This is also true for Strings where the compiler will append constant strings together if possible. The following does not use a StringBuilder at runtime but instead will create a single String at compilation time:

    private static final String DEFAULT_HEADER = "A long headers that is " +
       "broker into two lines\n";
    

    But still, in both cases, the allocation and initialization of the fields (the long timeoutMillis and the String DEFAULT_HEADER) is done at runtime.

    If both static and final static variables would be created at run time, in the Main's first version neither of both static variables (instances and PI) of class MyClass would be created.

    In your example, the static fields (final or not) are allocated and initialized when the class is loaded for the first time. So in your first Main the instances or PI static fields will never be created like you mention. In your 2nd example. as soon as MyClass is referenced, the class file will be loaded and the static fields created.