【问题标题】:Problem with illegal forward reference in Java [duplicate]Java中非法前向引用的问题[重复]
【发布时间】:2019-05-02 09:39:38
【问题描述】:

为什么当我在变量声明中使用引用this 时,不会出现非法前向引用?声明this和不声明有什么区别?

以下示例由于非法前向引用而无法编译:

class FailsToCompile {
    int a = b; //illegal forward reference
    int b = 10;
}

通过this 限定对b 的使用,编译错误消失了。

class Compiles {
    int a = this.b; //that's ok
    int b = 10;
}

【问题讨论】:

  • @Pshemo 我认为它背后的机制是一样的,不是吗?所以这应该算作重复
  • @Lino 你可能是对的,但由于我还没有读过那篇文章,所以我不想仅仅根据概率使用我的欺骗锤。
  • 欢迎来到 Stack Overflow!请阅读“如何创建minimal reproducible example”。然后使用edit 链接改进您的问题(不要通过 cmets 添加更多信息)。否则我们无法回答您的问题并为您提供帮助。含义:范围在这里非常重要,你的代码sn-ps完全忽略了范围!
  • 我建议(基于没有确凿的证据)禁止前向引用只是一种尽力而为的尝试"to catch, at compile time, circular or otherwise malformed initializations"。例如,您还可以通过方法调用前向引用变量。因此,它会捕获明显错误的代码,但如果您真的要坚持自己知道自己在做什么,它不会太努力地阻止您。

标签: java


【解决方案1】:

假设以下类

public class MyClass {
    int a = b;
    int b = 10;
}

JLS 8.3.3. 状态在您的情况下:

实例变量的使用有时会受到限制
- 使用是 C 的实例变量初始化器或 C 的实例初始化器中的简单名称

现在,使用成员 this 允许您访问已使用默认值 (a = 0, b = 0) 声明但尚未完全初始化的实例。如果您检查以下结果,这是可见的:

public class MyClass {
    int a = this.b;
    int b = 10;
}

你不会得到预期值:

new MyClass().a //0
new MyClass().b //10

我无法解释为什么这是合法的,因为这永远不会给出正确的值。我们可以找到一些关于为什么存在限制的解释:

上述限制旨在在编译时捕获循环或其他格式错误的初始化。

但是为什么允许this 工作......


知道在实例初始化期间,会发生以下操作:

  1. 成员声明
  2. 按顺序执行块和字段初始化
  3. 构造函数执行

给出一些奇怪的行为:

public class MyClass {

    {
        b = 10;
    }
    int a = this.b;
    int b = 5;
    {
        b = 15;
    }

    public static void main(String[] args) {
        MyClass m = new MyClass();
        System.out.println(m.a); //10
        System.out.println(m.b); //15
    }
}

我会限制构造函数中的初始化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 2011-07-29
    相关资源
    最近更新 更多