Java:静态初始化
Java: Static initialization
你能解释一下两者之间的区别吗:
public class Test {
public static final Person p;
static {
p = new Person();
p.setName("Josh");
}
}
和
public class Test {
public static final Person p = initPerson();
private static Person initPerson() {
Person p = new Person();
p.setName("Josh");
return p;
}
}
我一直使用第二种,但是与静态初始化块有什么区别吗?
initPerson 需要在某个时候调用,而静态块在创建 Test 对象时执行。
每次调用都会执行一个静态方法(第二个例子)。静态初始化块(第一个示例)仅在初始化 class.
时调用一次
http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
The advantage of private static methods is that they can be reused later if you need to reinitialize the class variable.
这不算 final
个实例,因为 final 变量只能初始化一次。
当然存在技术差异(如果你愿意,你可以在你的 class 中多次调用静态方法,你可以通过反射等调用它)但是,假设你不做任何那个诡计,你是对的——这两种方法实际上是相同的。
我也更喜欢基于方法的方法,因为它给代码块起了一个好听的名字。但这几乎完全是一种文体方法。
正如 Marko 指出的那样,基于方法的方法还用于分离创建 Person 并将其分配给静态变量这两个问题。对于静态块,这两件事结合在一起,如果块不平凡,这会损害可读性。但是对于方法方法,方法仅负责创建对象,而静态变量的初始化仅负责获取该方法的结果和将其分配给变量。
更进一步:如果我有两个静态字段,并且一个依赖于另一个,那么我将声明两个方法,并让第二个方法将第一个变量作为显式参数。我喜欢让我的静态初始化方法 完全 没有状态,这使得更容易推断出应该在什么时候发生(以及它假定已经创建了哪些变量)。
所以,类似于:
public class Test {
public static final Person p = initPerson();
public static final String pAddress = lookupAddress(p);
/* implementations of initPerson and lookupAddress omitted */
}
很明显,(a) 您不需要 pAddress
来初始化 p
,并且 (b) 您 需要 需要p
来初始化lookupAddress
。事实上,如果您以相反的顺序尝试它们并且您的静态字段不是 final
:
,编译器会给您一个编译错误 ("illegal forward reference")
public static String pAddress = lookupAddress(p); // ERROR
public static Person p = initPerson();
你会失去静态块的清晰度和安全性。这编译得很好:
static {
pAddress = p.findAddressSomehow();
p = new Person();
}
...但它会在 运行 时失败,因为在 p.findAddressSomehow()
时,p
的默认值为 null
。
函数前的静态指定您可以通过在 Class 名称句柄本身上调用它来使用该函数。例如,如果你想在 class 之外创建一个 Person 对象,你可以写
Person p = Test.initPerson();
但是,两者之间没有优势区别,因为在这两种情况下都可以访问 class 之外的对象 p。
你能解释一下两者之间的区别吗:
public class Test {
public static final Person p;
static {
p = new Person();
p.setName("Josh");
}
}
和
public class Test {
public static final Person p = initPerson();
private static Person initPerson() {
Person p = new Person();
p.setName("Josh");
return p;
}
}
我一直使用第二种,但是与静态初始化块有什么区别吗?
initPerson 需要在某个时候调用,而静态块在创建 Test 对象时执行。
每次调用都会执行一个静态方法(第二个例子)。静态初始化块(第一个示例)仅在初始化 class.
时调用一次http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
The advantage of private static methods is that they can be reused later if you need to reinitialize the class variable.
这不算 final
个实例,因为 final 变量只能初始化一次。
当然存在技术差异(如果你愿意,你可以在你的 class 中多次调用静态方法,你可以通过反射等调用它)但是,假设你不做任何那个诡计,你是对的——这两种方法实际上是相同的。
我也更喜欢基于方法的方法,因为它给代码块起了一个好听的名字。但这几乎完全是一种文体方法。
正如 Marko 指出的那样,基于方法的方法还用于分离创建 Person 并将其分配给静态变量这两个问题。对于静态块,这两件事结合在一起,如果块不平凡,这会损害可读性。但是对于方法方法,方法仅负责创建对象,而静态变量的初始化仅负责获取该方法的结果和将其分配给变量。
更进一步:如果我有两个静态字段,并且一个依赖于另一个,那么我将声明两个方法,并让第二个方法将第一个变量作为显式参数。我喜欢让我的静态初始化方法 完全 没有状态,这使得更容易推断出应该在什么时候发生(以及它假定已经创建了哪些变量)。
所以,类似于:
public class Test {
public static final Person p = initPerson();
public static final String pAddress = lookupAddress(p);
/* implementations of initPerson and lookupAddress omitted */
}
很明显,(a) 您不需要 pAddress
来初始化 p
,并且 (b) 您 需要 需要p
来初始化lookupAddress
。事实上,如果您以相反的顺序尝试它们并且您的静态字段不是 final
:
public static String pAddress = lookupAddress(p); // ERROR
public static Person p = initPerson();
你会失去静态块的清晰度和安全性。这编译得很好:
static {
pAddress = p.findAddressSomehow();
p = new Person();
}
...但它会在 运行 时失败,因为在 p.findAddressSomehow()
时,p
的默认值为 null
。
函数前的静态指定您可以通过在 Class 名称句柄本身上调用它来使用该函数。例如,如果你想在 class 之外创建一个 Person 对象,你可以写
Person p = Test.initPerson();
但是,两者之间没有优势区别,因为在这两种情况下都可以访问 class 之外的对象 p。