本文介绍了静态最终字段的非正向引用错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用非法转发引用错误编译 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;
    }
});

这篇关于静态最终字段的非正向引用错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-13 12:22