根据JLS,'T.super'是一个合法表达吗?

时间:2016-01-07 17:56:15

标签: java eclipse java-8 super 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(火星​​) 编译这没有任何错误,结果是:

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对{的理解{1}})进入局部变量T.super。执行代码时,代码正常完成,行o生成正确的结果。

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

根据JLS,o = T.super;是合法表达吗?

<小时/> 编辑:通过删除包装内部类来简化代码。

4 个答案:

答案 0 :(得分:13)

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

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

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

答案 1 :(得分:3)

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

您的类定义可以像这样查看(使用命名的内部类):

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

引用外部类的正确方法是

Outer o = Outer.this; // valid

答案 2 :(得分:2)

接受这种语法是一个长期存在的bug in Eclipse,已针对里程碑5修复了Eclipse 4.6。

答案 3 :(得分:-1)

根据JLS,这是正确的。 JLS规范“表单super.Identifier是指当前对象的名为Identifier的字段,但当前对象被视为当前类的超类的实例。”

基于此super是超类的实例。

JLS还指出“如果当前类不是类T或T本身的内部类,那么这是一个编译时错误。”

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