问题描述
我正在尝试使用非法转发引用错误编译 javac
拒绝的Java类,其中违规引用是词法 引用字段后。在显示相同行为时,尽可能地删除以下类:
I'm trying to compile a Java class which javac
rejects with an illegal forward reference error, where the offending reference is lexically after the referenced field. The following class is stripped down as much as possible while showing the same behavior:
java.util.concurrent.Callable
以及 Object
的许多用法仅用作占位符以删除不相关的代码段。
java.util.concurrent.Callable
and the many uses of Object
are just used as placeholders to remove irrelevant pieces of code.
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;
}
}
使用编译时javac测试.java
,javac打印以下错误消息:
When compiled using javac Test.java
, javac prints the following error message:
Test.java:9: illegal forward reference
static final Object bar = foo;
^
所以编译器抱怨 bar
的声明引用 foo
而 foo
应该在 bar的范围内
的声明。但是一旦 bar
中的 bar
的引用被删除,例如通过从返回栏更改第5行;
到返回null;
,编译器接受该类。
So the compiler complains about bar
's declaration referencing foo
while foo
should be in the scope of bar
's declaration. But as soon as the reference of bar
in foo
's declaration is removed, e.g. by changing line 5 from return bar;
to return null;
, the class is accepted by the compiler.
如何解释这个?在错误之后,我对转发的理解是意义吗?或者这是一些我不知道的特殊情况?
How can this be explained? Is my understanding of forward as meaning lexically after wrong or is this some special case I'm not aware of?
推荐答案
您对前向参考的理解是正确的。第9行对 foo
的引用根本不是转发引用,因为它在声明之前不会以文本形式出现(参见定义)。
Your understanding of forward reference is correct. The reference to foo
on line 9 isn't a forward reference at all since it doesn't appear textually before its declaration (see the definition of what constitutes a forward reference in section 8.3.2.3 of The Java Language Specification).
您观察到的行为是javac bug 的症状。请参阅。该问题似乎在较新版本的编译器中得到修复,例如。
The behavior you observe is a symptom of a javac bug. See this bug report. The problem appears to be fixed in newer versions of the compiler, e.g. OpenJDK 7.
它仅影响用作最终字段的初始值设定项的转发引用。该问题似乎同样影响静态和非静态字段。
It only affects forward references used as initializers to final fields. The issue appears to affect static and non-static fields equally.
请注意栏
对<$的引用c $ c> call()是合法的转发引用,因为它发生在不同的类中(参见。
Note that the reference to bar
in call()
is a legal forward reference since it occurs inside a different class (see examples in section 8.3.2.3 of The Java Language Specification).
另外,请注意以下每个更改都会使错误消失:
Also, note that each of the following alterations make the error disappear:
使栏
非最终:
static Object bar = foo;
在静态或实例初始化程序块中初始化 bar
:
Initializing bar
in static or instance initializer block:
static final Object bar;
static {
bar = foo;
}
移动 foo初始化
到初始化程序块也有帮助。
Moving the initialization of foo
to an initializer block also helps.
从非最终临时引用<$ c初始化 bar
$ c> foo :
Initializing bar
from a non-final temporary reference to foo
:
static Object tmp = foo;
static final Object bar = tmp;
使用 bar > Test.foo (由Tom Anderson发现)或 this.foo
在非静态情况下:
Initializing bar
with Test.foo
(found by Tom Anderson) or with this.foo
in non-static case:
static final Object bar = Test.foo;
删除栏
并使用对象引用 foo
里面 call()
:
Removing bar
and referring to the object using foo
inside call()
:
static final Object foo = method(new java.util.concurrent.Callable<Object>() {
@Override
public Object call() throws Exception {
return foo;
}
});
这篇关于静态最终字段的非正向引用错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!