This is the job of the class loader. The class loading in java starts with the bootstrap classloader. This class loader first loads all the classes in the standard java library, the rt.jar.
Then the extension classloader is invoked. This loads all the classes from the extension jar files installed in a JVM ext directory. Now finally the classpath classloader is invoked.
The classpath classloader starts loading classes from the main class, the class that has the main method defined. Once it is loaded, it executes any static initializers in that class. While in the execution of the initializer, if it encounters any class that is not loaded, it will pause the execution of the static block, loads the class first, and finally resumes the execution of that static block.
So, there is no chance that any calls to non-loaded classes to occur. Let's see this with your own example, whose code is like this:
class A
{
public final static List<Integer> list;
static
{
System.out.println("Loaded Class A");
list = new ArrayList<>();
}
}
class B
{
public final static int dependsOnA;
static
{
System.out.println("Loaded Class B");
dependsOnA = A.list.size();
}
}
Here in this example, there is actually no main method, so these classes won't actually be loaded into the memory. Suppose, let's add the following main class to the above code.
class C
{
static
{
System.out.println("Loaded Class C");
}
public static void main(String[] args)
{
System.out.println(B.dependsOnA);
}
}
Let's see what this would produce in the output: http://ideone.com/pLg3Uh
Loaded Class C
Loaded Class B
Loaded Class A
0
That is, first the class C is loaded, because it had the main method. Once it is loaded, the static initializer of class C is invoked. Notice, however, that the main method is invoked after the static block of class C is loaded.
Now the main method, we printed the value of dependsOnA
of class B. Now, the class loader stops executing that statement, and loads the class B, and executes it's static block, which in turn, assigns the dependsOnA
variable with the value of the number of elements in the list of class A, which is not loaded.
So the class loader jumps from there, loads the class now, and invokes the static block of the class A, and a list is created. Now since there are no more classes to load, the class loader comes back to the static block of class B, and assignment is complete. Now finally, the control is now with the main method, and the value of dependsOnA
is printed to the console.
Hope this helps.