看下面一段代码:
  public class LinkTest {
  public static void main(String[] args) {
  ToBeLinked toBeLinked = null;
  System.out.println("Test link.");
  }
  }
  类 LinkTest引用了类ToBeLinked,但是并没有真正使用它,只是声明了一个变量,并没有创建该类的实例或是访问其中的静态域。如果把编译好的ToBeLinked的Java字节代码删除之后,再运行LinkTest,程序不会抛出错误。这是因为ToBeLinked类没有被真正用到。链接策略使得ToBeLinked类不会被加载,因此也不会发现ToBeLinked的Java字节代码实际上是不存在的。如果把代码改成ToBeLinked toBeLinked = new ToBeLinked();之后,再按照相同的方法运行,会抛出异常了。因为这个时候ToBeLinked这个类被真正使用到了,会需要加载这个类。
  三、Java类的初始化
  开发 Java 时,接触多的是对象的初始化。实际上类也是有初始化的。相比对象初始化,类的初始化机制要简单不少。
  类的初始化也是延迟的,直到类第一次被主动使用(active use),JVM 才会初始化类。
  当一个Java类第一次被真正使用到的时候,JVM会进行该类的初始化操作。初始化过程的主要操作是执行静态代码块和初始化静态域。在一个类被初始化之前,它的直接父类也需要被初始化。但是,一个接口的初始化,不会引起其父接口的初始化。在初始化的时候,会按照源代码中从上到下的顺序依次执行静态代码块和初始化静态域。
  public class StaticTest {
  public static int X = 10;
  public static void main(String[] args) {
  System.out.println(Y); //输出60
  }
  static {
  X = 30;
  }
  public static int Y = X * 2;
  }
  在上面的代码中,在初始化的时候,静态域的初始化和静态代码块的执行会从上到下依次执行。因此变量X的值首先初始化成10,后来又被赋值成30;而变量Y的值则被初始化成60。
  类的初始化分两步:
  1.如果基类没有被初始化,初始化基类。
  2.有类构造函数,则执行类构造函数。
  类构造函数是由 Java 编译器完成的。它把类成员变量的初始化和 static 区间的代码提取出,放到一个<clinit>方法中。这个方法不能被一般的方法访问(注意,static final 成员变量不会在此执行初始化,它一般被编译器生成 constant 值)。同时,<clinit>中是不会显示的调用基类的<clinit>的,因为 1 中已经执行了基类的初始化。该初始化过程是由 Jvm 保证线程安全的。。
  Java类和接口的初始化只有在特定的时机才会发生,这些时机包括:
  创建一个Java类的实例。如
  MyClass obj = new MyClass()
  调用一个Java类中的静态方法。如
  MyClass.sayHello()
  给Java类或接口中声明的静态域赋值。如
  MyClass.value = 10
  访问Java类或接口中声明的静态域,并且该域不是常值变量。如
  int value = MyClass.value
  在顶层Java类中执行assert语句。
  通过Java反射API也可能造成类和接口的初始化。需要注意的是,当访问一个Java类或接口中的静态域的时候,只有真正声明这个域的类或接口才会被初始化。考虑下面的代码:
class B {
static int value = 100;
static {
System.out.println("Class B is initialized."); //输出
}
}
class A extends B {
static {
System.out.println("Class A is initialized."); //不会输出
}
}
public class InitTest {
public static void main(String[] args) {
System.out.println(A.value); //输出100
}
}
  在上述代码中,类InitTest通过A.value引用了类B中声明的静态域value。由于value是在类B中声明的,只有类B会被初始化,而类A则不会被初始化。