静态最终字段的非法前向引用错误 [英] Illegal forward reference error for static final fields

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

问题描述

我正在尝试编译一个 javac 拒绝的 Java 类,并出现一个非法前向引用错误,其中有问题的引用在词法上after引用的字段.以下类在显示相同行为的同时被尽可能地精简:

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.CallableObject 的许多用途只是用作占位符来删除不相关的代码.

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 Test.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 的声明引用了 foofoo 应该在 bar 的范围内> 的声明.但是一旦 foo 声明中的 bar 引用被删除,例如通过将第 5 行从 return bar; 更改为 return 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.

这怎么解释?我对forward 的理解是词法上的意思 是错误的还是我不知道的一些特殊情况?

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 的引用根本不是前向引用,因为它在声明之前没有以文本形式出现(请参阅构成的定义)Java 语言规范的第 8.3.2.3 节中的前向引用).

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 错误 的症状.请参阅此错误报告.该问题似乎已在较新版本的编译器中得到解决,例如OpenJDK 7.

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.

它只影响用作 final 字段的初始值设定项的前向引用.该问题似乎同样影响静态和非静态字段.

It only affects forward references used as initializers to final fields. The issue appears to affect static and non-static fields equally.

请注意,call() 中对 bar 的引用是合法的前向引用,因为它出现在不同的类中(请参阅Java 语言规范的第 8.3.2.3 节).

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:

使 bar 成为非最终的:

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.

从对 foo 的非最终临时引用初始化 bar:

Initializing bar from a non-final temporary reference to foo:

static Object tmp = foo;
static final Object bar = tmp;

使用 Test.foo(由 Tom Anderson 发现)或在非静态情况下使用 this.foo 初始化 bar:

Initializing bar with Test.foo (found by Tom Anderson) or with this.foo in non-static case:

static final Object bar = Test.foo;

移除 bar 并在 call() 中使用 foo 引用对象:

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;
    }   
});

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆