Feu*_*mel 12 java javac forward-declaration
我正在尝试编译一个javac拒绝非法前向引用错误的Java类,其中违规引用是在引用字段之后的词法上.在显示相同行为时,尽可能地删除以下类:
java.util.concurrent.Callable并且许多用途Object仅用作占位符来删除不相关的代码片段.
public class Test {
static final Object foo = method(new java.util.concurrent.Callable<Object>() {
@Override
public Object call() throws Exception {
return bar;
}
});
static final Object bar = foo;
static Object method(Object binder) {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
使用时编译javac Test.java,javac打印以下错误消息:
Test.java:9: illegal forward reference
static final Object bar = foo;
^
Run Code Online (Sandbox Code Playgroud)
所以编译器抱怨bar声明引用的foo同时foo应该在bar声明的范围内.但是一旦删除了barin foo的声明的引用,例如通过将第5行更改return bar;为return null;,则编译器接受该类.
怎么解释这个?是我的理解向前的意思后词法错误或这是一些特殊的情况下,我不知道的?
Ada*_*man 16
您对前向参考的理解是正确的.foo对第9行的引用根本不是前向引用,因为它在声明之前没有以文本形式出现(参见Java语言规范第8.3.2.3节中构成前向引用的定义).
您观察到的行为是javac bug的症状.请参阅此错误报告.问题似乎在较新版本的编译器中得到修复,例如OpenJDK 7.
它仅影响用作最终字段的初始值的前向引用.该问题似乎同样影响静态和非静态字段.
请注意,对barin 的引用call()是合法的前向引用,因为它出现在不同的类中(请参阅Java语言规范的第8.3.2.3节中的示例).
另请注意,以下每个更改都会使错误消失:
进行bar非决赛:
static Object bar = foo;
Run Code Online (Sandbox Code Playgroud)
初始化bar静态或实例初始化块:
static final Object bar;
static {
bar = foo;
}
Run Code Online (Sandbox Code Playgroud)
将初始化移动foo到初始化块也有帮助.
bar从非最终临时引用初始化为foo:
static Object tmp = foo;
static final Object bar = tmp;
Run Code Online (Sandbox Code Playgroud)
bar使用Test.foo(由Tom Anderson发现)或this.foo在非静态情况下初始化:
static final Object bar = Test.foo;
Run Code Online (Sandbox Code Playgroud)
bar使用foo内部删除和引用对象call():
static final Object foo = method(new java.util.concurrent.Callable<Object>() {
@Override
public Object call() throws Exception {
return foo;
}
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7032 次 |
| 最近记录: |