我想知道何时将静态变量初始化为其默认值。加载类时,创建(分配)静态变量,然后执行静态初始化程序和声明中的初始化是否正确?在什么时候给出默认值?这导致前向参考的问题。
另外,如果您可以参考“为什么没有及时初始化静态字段?”这一问题进行解释,尤其是Kevin Brock在同一站点上给出的答案。我不明白第三点。
我想知道何时将静态变量初始化为其默认值。加载类时,创建(分配)静态变量,然后执行静态初始化程序和声明中的初始化是否正确?在什么时候给出默认值?这导致前向参考的问题。
另外,如果您可以参考“为什么没有及时初始化静态字段?”这一问题进行解释,尤其是Kevin Brock在同一站点上给出的答案。我不明白第三点。
Answers:
- 它是一个属于类而不属于对象(实例)的变量
- 静态变量在执行开始时仅初始化一次。在初始化任何实例变量之前,将首先初始化这些变量
- 该类的所有实例共享一个副本
- 静态变量可以通过类名直接访问,不需要任何对象。
如果您没有故意将实例和类(静态)变量初始化为标准默认值,则将它们自动初始化为标准默认值。尽管不会自动初始化局部变量,但是您无法编译在使用局部变量之前无法初始化局部变量或为该局部变量赋值的程序。
编译器实际上所做的是内部生成一个单一的类初始化例程,该例程将所有静态变量初始化器和所有静态初始化器代码块按它们在类声明中出现的顺序组合在一起。第一次加载类时,仅一次自动运行一次初始化过程。
对于内部类,它们不能具有静态字段
一个内部类是没有明确或隐含声明的嵌套类
static
。...
内部类可能未声明静态初始化器(第8.7节)或成员接口。
内部类不能声明静态成员,除非它们是常量变量。
请参见JLS 8.1.3内部类和封闭实例
final
Java中的字段可以与其声明位置分开进行初始化,但是这不适用于static final
字段。请参见下面的示例。
final class Demo
{
private final int x;
private static final int z; //must be initialized here.
static
{
z = 10; //It can be initialized here.
}
public Demo(int x)
{
this.x=x; //This is possible.
//z=15; compiler-error - can not assign a value to a final variable z
}
}
这是因为与该类型关联的变量只有一个副本static
,而不是与实例变量一样与该类型的每个实例关联的副本,并且如果我们尝试在构造函数中初始化z
类型static final
,它将尝试重新初始化static final
类型字段z
因为构造函数是在类的每个实例化上运行的,这些实例化不能在静态final
字段中发生。
In case of static inner classes, they can not have static fields
好像是错字。内部类是非静态的。
从另一个问题的代码开始:
class MyClass {
private static MyClass myClass = new MyClass();
private static final Object obj = new Object();
public MyClass() {
System.out.println(obj); // will print null once
}
}
对此类的引用将开始初始化。首先,该类将被标记为已初始化。然后,将使用MyClass()的新实例初始化第一个静态字段。请注意,立即为myClass提供了对空白MyClass实例的引用。有空格,但所有值都为空。现在执行构造函数并打印obj
,这是空的。
现在回到初始化类: obj
引用了一个新的真实对象,我们就完成了。
如果这是通过类似以下语句的语句来取消的: MyClass mc = new MyClass();
则将再次分配用于新MyClass实例的空间(并将引用放置在中mc
)。构造函数将再次执行并再次打印obj
,现在不为null。
真正的窍门是,当您使用时new
,WhatEverItIs weii = new WhatEverItIs( p1, p2 );
weii
会立即为in提供一个对一些空内存的引用。然后,JVM将继续初始化值并运行构造函数。但是,如果你以某种方式引用weii
之前它这样做-从另一个线程或引用,或通过从类初始化引用,例如-你正在寻找使用null值填充一个类的实例。
静态变量可以通过以下三种方式初始化,如下所示,选择任意一种
或者您可以通过制作静态块来实现,例如:
static {
// whatever code is needed for initialization goes here
}
静态块有替代方法-您可以编写私有的静态方法
class name {
public static varType myVar = initializeVar();
private static varType initializeVar() {
// initialization code goes here
}
}