静态变量初始化

时间:2011-08-31 15:12:18

标签: java

每次创建包含这些变量的对象的新实例时,是否会初始化静态变量?或者在首次调用对象时它们只被初始化一次?

2 个答案:

答案 0 :(得分:11)

你说

初始化实例静态变量 ...

在那里停下来,声明毫无意义。静态变量存在于类中,而不是任何特定实例上。它们在初始化过程中初始化,该过程在创建实例,运行类上的静态方法或访问类上的静态变量时运行。 (完全披露,@ Bruno的回答让我了解了这个信息)。

答案 1 :(得分:3)

静态字段在类的初始化期间初始化(不要混合初始化加载,它们是不同的东西 - a class可以被加载,你可以对它进行反射,而无需初始化它。)

此外,如果您使用多个ClassLoader s,则对于给定的类,类初始化可能会多次发生。

请参阅VM Spec section 2.17.4, Initializationsection 2.17.5, Detailed initialization procedure,详细了解何时加载一个类以及何时将其初始化。

编辑:一个简单的例子,它将显示如何加载一个类多次初始化,并且加载不会自动暗示初始化:

public class A { static { System.out.println("I've been initialized!"); } }
public class Main {
  public static void main(String... args) {
    ClassLoader cl = new URLClassLoader(..., null);
    System.out.println("loading...");
    Class<?> aClass = cl.loadClass("A");
    // here you could perform reflection on aClass, without initializing it
    System.out.println("Will be initialized now:");
    Object o = aClass.newInstance();
    System.out.println("Let's load once again...");
    ClassLoader cl2 = new URLClassLoader(..., null);
    Class<?> aClass2 = cl2.loadClass("A");
    System.out.println("Will be initialized a second time:");
    Object o2 = aClass2.newInstance();

    // the following is false:
    System.out.println("aClass1.equals(aClass2) = " + aClass1.equals(aClass2));

    // the following is true:
    System.out.println("aClass1.getName().equals(aClass2.getName())" + aClass1.getName().equals(aClass2.getName()));
  }
}

(我希望在URLClassLoader的构造函数中指定缺少的URL[]对象时进行编译...)

请注意,有必要设置类加载器的父级null,否则它们的父级将是主应用程序类加载器(即加载类Main的相同),然后因为Java默认情况下首先将加载委托给父类加载器,如果类A在类路径中,您只会看到加载和初始化一次。

最后,请注意Class.load("A")不等同于classLoader.loadClass("A")。如果您查看Class.load(String)的文档,您会看到此方法加载初始化该类。有Class.load(...)的重载,它带有一个布尔值,表明它是否应该初始化类。