This is a somewhat subjective question but I like it.
As you wrote correctly, one big reason is for early error detection. If the compiler does not have the class files of dependent classes for reference it has to assume that every external reference is correct. Any errors in these can be only detected at run time. You don't want this.
There are holes here though. The dependent class can change later. For this reason and others, the available class definition at run time can be different from the one used at compile time resulting in runtime errors.
But what we have is better than the alternative.
There are some cases where elements from referenced classes is integrated into the current compilation unit, for example "constants". Consider the following two classes:
// File A1.java
class A1 {
static final String s = "string"; // constant
static String s2 = "string2"; // not constant
static final int i = 5; // constant
}
// File A2.java
class A2 {
public static void main(String args[]) {
System.out.println("A1.s: " + A1.s);
System.out.println("A1.s2: " + A1.s2);
System.out.println("A1.i: " + A1.i );
}
}
Compile these two and then study the output of javap -c -l -private A2 and note the following:
- The references to A1.s and A1.i include the actual values
- If you remove the reference to
A1.s2 then java A2 can be executed even if A1.class is deleted