我正在尝试遵循JVM规范http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.4.2。 阅读不清楚的规格令我感到沮丧。所以: 有什么区别:
类变量初始值设定项
类的静态初始值设定项
字段初始值设定项
/ * Initalizers * /
class A {
private static String x = "sfi"; //static field initializer
private String ifi = "ifi"; //instance field initializer
static { //static (block) initalizer ?!
String y = "sbi";
}
{ //instance (block) initalizer ?!
String z = "ibi";
}
}
答案 0 :(得分:1)
首先,您需要了解类的静态和非静态字段之间的区别。 静态字段未绑定到类的任何实例,它是类的属性(这就是我们通过类访问它们的原因)所以在您的示例中,您可以访问{{1来自whithin x
就像这样:A
。一个常见的例子是计算一个类的对象数:
A.x
我们可以从其他地方调用此方法:private static int counter = 0;
public A()
{
counter++;
}
// get the instance count
public static int getCounter()
{
return counter;
}
我们将检索类型为A.getCounter()
的对象数。
这些是特定于类的每个对象(实例)的变量。在您的示例中,这是A
。运行时系统保证只要创建sfi
类型的对象并且它的默认值为 ifi ,sfi
就可用,但这里的区别在于每个您创建的对象将有一个名为A
的成员,其默认值为 ifi ,因此每个对象可以在以后修改它。
它们是一种在初始化无法内联时使用的功能(初始化需要更复杂的逻辑,如sfi
循环或错误检查)。我们再次在这里:
for
这是一个静态初始化块,它可以出现在类体中的任何地方。运行时系统保证静态初始化块按照它们出现在源代码中的顺序被调用" - 来自here
另一方面,如果我们要初始化实例成员,但我们无法在一行中执行,那么我们可以使用一个块但不使用static { /* init code ... /* }
关键字:
static
Java编译器将初始化程序块复制到每个构造函数中。因此,这种方法可用于在多个构造函数之间共享代码块。