'T.super' 是 JLS 的合法表达式吗?

Is 'T.super' a legal expression as per JLS?

考虑以下一组表达式:

class T {{
/*1*/   Object o = T.super; // error: '.' expected
/*2*/   o.toString();
}}

试图编译它会 在行 /*1*/ 上失败 并出现错误:

error: '.' expected
    o = T.super;
               ^

使用 OpenJDK 1.8.0 (Ubuntu)Oracle JDK 1.8 (Windows).

然而,Eclipse 4.5.0 (Mars)编译这没有任何错误,结果是:

class T {
    T();
     0  aload_0 [this]
     1  invokespecial java.lang.Object() [8] // super()
     4  aload_0 [this]
     5  astore_1 [o]  // o = T.super
     7  invokevirtual java.lang.Object.toString() : java.lang.String [10]
    10  pop           // ^-- o.toString()
    11  return
}

由此您可以看到 java 代码的 /*1*/ 行(结果的 5 行)正确存储了 this 转换为 Object(Eclipse对T.super的理解)写入局部变量o。执行代码时,它正常完成并且行 /*2*/ 产生正确的结果。

到目前为止,我没能在 Java 8 Language Specification 中找到任何与 o = T.super; 相关的内容,即它是否合法。由于它没有明确声明它是一个合法的表达式,我的猜测是它意味着它是 非法的 。但是,为什么 Eclipse 认为它是合法的呢?因此我的问题是:

T.super 是 JLS 的合法表达式吗?


编辑:通过删除内部包装简化了代码 class。

T.super 不是合法的表达式,因为它没有意义。 super(带或不带显式类型)语法仅用于从超 class 调用方法。 T.super 不调用任何方法(如果它是合法的语法),它只引用一个 class 实例。在您的情况下,它引用 outer T 实例。正确的语法是 T.this,它指向 outer this.

您的 class 定义可以这样查看(带有命名的内部 class):

class Outer
{
    // Constructor Body
    {
        class Inner
        {{
            /*1*/   Outer o = Outer.super; // error: '.' expected
            /*2*/   o.toString();
        }};
        new Inner();
    }
}

引用外部 class 的正确方法是

Outer o = Outer.this; // valid

不,不是。参考Chapter 19。搜索关键字 super 会产生以下结构:

  • 通配符范围:extends T / super T
  • 显式构造函数调用:super(args)
  • 字段访问:[Typename.]super.field
  • 方法调用:[Typename.]super.method()
  • 方法参考:super::method.

它编译的事实可能被认为是错误或语言扩展,尽管两者之间没有真正的区别。

根据 JLS,这是正确的。 JLS 规格 "The form super.Identifier refers to the field named Identifier of the current object, but with the current object viewed as an instance of the superclass of the current class. "

基于这个super是super的实例class.

JLS 还指出 "It is a compile-time error if the current class is not an inner class of class T or T itself."

在你的情况下,它显然是一个内部 class。你能找出eclipse中使用的Java的版本吗?

接受此语法是 long-standing bug in Eclipse,已针对 Eclipse 4.6 的里程碑 5 进行了修复。