Java中的初始化顺序

5
我想问为什么 Java 在初始化非静态对象之前会先初始化静态对象?
在这个例子中,b3 会在 b4 和 b5 之后被初始化:
class Cupboard { 
    Bowl b3 = new Bowl(3); 
    static Bowl b4 = new Bowl(4); 
    Cupboard() {}
    static Bowl b5 = new Bowl(5); 
}
5个回答

17
因为类的静态成员在创建和初始化时(在类加载期间)比任何类实例都早创建,所以它们可以在不创建类实例的情况下进行访问。非静态成员是按实例创建的,因此等待实例被创建才对该实例进行初始化。

谢谢Dav,但是“类加载”是什么时候发生的?是在编译之后还是当我想要从类中创建一个实例时? - Mohamad Alhamoud
@M.H:你的类在第一次尝试使用它时被动态加载,或者如果你明确告诉虚拟机去加载它。在那个时候,静态内容被初始化。如果编译器可以在编译时确定这些值,那么其中一些值可能已经被内联化了。 - Mr. Shiny and New 安宇
很方便,今天发布的这篇文章解释得相当清楚:http://www.developer.com/java/other/article.php/2248831/Java-Class-Loading-The-Basics.htm 然而,总结一下,JVM规范要求在第一次活动使用该类型之前必须发生该类型的静态成员的初始化。除此之外,就由虚拟机实现来决定了。 - Amber

3
因为类在实例化之前被初始化。当类被加载时,Java会运行任何静态块并初始化静态变量。然而,非静态的实例变量直到创建一个实例后才会被创建和初始化。

2

当类被加载时,静态变量会被初始化。

当实例被构造时,实例变量会被初始化。大多数情况下,这是在类完全初始化之后进行的,但与其他人所写的相反,这也可能发生在初始化静态变量时。例如,通常会有静态常量表示类的常用实例,如下所示:

class Foo
{
    private static final Foo FOO_BAR = new Foo("bar");
    private static final Foo FOO_BAZ = new Foo("baz");

    private final String name;

    public Foo(String n)
    {
        name = n;
    }

    [...]
}

在FOO_BAZ初始化之前,首先将名称初始化为“bar”。


2
  • static变量在类被加载时初始化。

  • 实例变量(非静态)在该类的对象构造后初始化,这是在类加载之后进行的。


1

想象一下,静态变量是类的变量,而不是该类的对象。这种情况有点高于实例级别。如果Java支持元类,那么在声明它们时,类将从元类实例化,并且即使不存在这些类的实例,也可以访问它们的静态成员。因此,在非静态成员之前确实需要静态成员。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接