我有两个关于静态块和常量的问题,下面是代码。
我想知道为什么会这样?
代码:
public class TestStaticblock {
static{
try {
// NAME = dummyStringValue() + NAME_APPENDER; // Cannot reference a field before it is defined
// NAME = dummyStringValue() + getNameAppender(); // This is OK
NAME = dummyStringValue();
} catch (Exception e) {
NAME = null; // The final field NAME may already have been assigned
}
}
private static String dummyStringValue() throws Exception{
return "dummy";
}
private static String getNameAppender() throws Exception{
return NAME_APPENDER;
}
private static final String NAME; // If I comment Catch it says "The blank final field NAME may not have been initialized"
private static String NAME_APPENDER = "appender";
}
答案 0 :(得分:2)
也许这会对那些寻找类似事物的人有所帮助。
Java有一个鲜为人知的特性(在Java专家Throwing Exceptions from Fields中讨论过),如果你想初始化一个final
实例变量(即 NOT a static
)方法调用的结果抛出异常然后您可以通过添加抛出异常的构造函数来避免明显的错误。
请注意,此解决方案仅适用于非静态(而不是您正在观察的内容)。
public class TestStaticblock {
private final String NAME = dummyStringValue();
// Adding this removes the "unreported Exception" above.
public TestStaticblock() throws Exception {
}
private static String dummyStringValue() throws Exception {
return "dummy";
}
}
答案 1 :(得分:2)
在分配之前,您不能在静态块中使用static final
字段,但只需调用方法即可访问它。
例如,此代码打印null FOO
:
public class Main {
static final String FOO;
static {
foo();
FOO = "FOOFOO".substring(0, 3);
foo();
}
static void foo() {
System.out.println(FOO);
}
public static void main(String[] args) {}
}
这无疑是奇怪的,但我想这会使语言变得更加复杂,以至于无法做到这一点。
至于你的第二个问题,这不会编译。
static{
try {
NAME = dummyStringValue();
} catch (Exception e) {
NAME = null; // The final field NAME may already have been assigned
}
}
这也很奇怪。如果抛出异常,则只能在方法dummyStringValue()
内发生。由于您无法为方法内的final
字段分配值,因此NAME
变量已完全无法在catch
块中分配。因此,没有可能的代码路径,其中未分配NAME
。你认为它应该以与
static{
if (someCondition()) {
NAME = dummyStringValue();
} else {
NAME = null;
}
}
编译好的。
我想原因再一次是它会让语言变得更加复杂。允许它没有什么好处,因为您可以使用其他答案中指示的方法或temp
变量。例外情况比if
语句更复杂 - 它们的行为几乎就像goto
。 @ElliottFrisch在评论中提出了一个很好的观点。这样的事情怎么样:
static{
try {
NAME1 = dummyStringValue1();
NAME2 = dummyStringValue2();
} catch (Exception e) {
// Has NAME1 been assigned here?
}
}
答案 2 :(得分:1)
我强烈的个人偏好是使用方法而不是初始化单个变量的静态初始化块:
private static final String NAME = getName();
private static String getName() {
try {
return something();
} catch (Exception e) {
return null;
}
}