【问题标题】:What is Illegal Self Reference in Java?什么是 Java 中的非法自引用?
【发布时间】:2019-10-12 06:13:43
【问题描述】:

当我尝试编译以下类时

class C1 {
  Integer v1 = v1;
}

我收到Illegal Self Reference 错误。现在考虑下面的另一个类。

class C2 {
  Integer v1;
  {
    v1 = v1;
  }
}

然后编译。这两个类有什么区别,为什么一个编译一个不编译。

更新:

如果v1 还没有在C1 类中可用,那么为什么下面的类也可以工作?

class C3 {
  Integer v1 = v1 = 1;
}

在上面的C3 类中,v1 可用于要评估的表达式v1 = 1,但它在C1 中的工作方式不同。你能解释一下吗?

【问题讨论】:

  • 区别是声明和声明+定义。
  • Integer v1 = v1 的情况下,变量v1 尚不存在,因此未定义 RHS。在您的第二种情况下,v1 已经定义。
  • 但是,Integer v1 = v1 = 1; 有效。如果这样的语法有效,那么这是否意味着v1 在 LHS 后就准备好了? @蒂姆·比格莱森
  • @AmrishKumar 之所以有效,是因为赋值是右关联的,所以 v1 在自赋值时有一个值。
  • @AmrishKumar 在C1中有一个没有初始化的成员声明,​​它得到一个默认值null,所以静态块中的赋值是合法的。

标签: java variable-declaration


【解决方案1】:

v1 在你定义后开始存在,所以当你尝试将值保存到自身时它还不存在:

class C1 {
    Integer v1 = v1;
//declaring-^     ^-doesn't exist yet
}

这是一个等价的代码:

public class SomeClass {
    Integer v1;

//声明....^

    public SomeClass() {
        this.v1 = v1;
//           ^-----^
//              |
//          both exist
    }
}

在您的示例中,实例块代码在声明变量后执行,就像构造函数一样:

class C2 {
  Integer v1;
  {
    v1 = v1;  // instance block executed after variable declaration
  }
}

更新问题的最后一部分在这里得到很好的解释https://softwareengineering.stackexchange.com/questions/205079/what-is-the-difference-advantage-of-doing-double-assignment

并在用户@user207421的评论中回答(关于正确关联)

【讨论】:

  • 我认为这与v1 的可用性无关,正如您在回答中所说的那样,C3 是我的证据。 @Damián Rafael Lattenero
  • @AmrishKumar 您的新示例再次不同。 Integer v1 声明变量(编译时),并在运行时将v1 = 1 作为表达式执行,其值被分配给v1。所以真的是Integer v1 = (v1 = 1);。你给v1一个值,所以它可以被引用。
  • @AmrishKumar 然而,你不应该做的是在你的问题得到回答后移动球门柱。您的 C3 部分本质上是一个新问题。
  • 我已经包含了C3 部分,作为v1 可用作C1 中RHS 变量的证据。早些时候,我不得不向关于这个问题的每一条评论解释这一点。我看不出这如何改变问题的原始动机。我在更新结束时引用了C1,但仍然只要求解释我之前的疑问。 @MartijnPieters
猜你喜欢
  • 2010-11-12
  • 1970-01-01
  • 1970-01-01
  • 2012-08-03
  • 1970-01-01
  • 1970-01-01
  • 2011-01-26
  • 2013-02-17
  • 1970-01-01
相关资源
最近更新 更多