【问题标题】:Compilation fails when using super in string concatination在字符串连接中使用 super 时编译失败
【发布时间】:2019-05-01 17:41:49
【问题描述】:

我有以下无法编译的类:

public class C {
    public String toString() {
        return "Test " + super;
    }
}

它给出了编译错误Syntax error on token "super", invalid Expression

有谁知道,为什么会出现这个编译器错误?预期的效果是"Test " + super.toString(),编译正常,但是为什么上面的例子编译失败呢?字符串连接的普通 Java 规则不应该在这里适用吗?

更令人惊讶的是,下面的代码编译得很好:

public String toString2() {
    return "Test " + this;
}

那么为什么this在字符串连接中起作用而super却没有呢?

我使用openjdk 11.0.3 2019-04-16,以防万一(我怀疑)。

【问题讨论】:

    标签: java inheritance tostring


    【解决方案1】:

    Java 中的super 关键字不是对象引用,因此您的代码中会出现一些错误! 这样做不是一个好习惯,因为super 是发现父类 的关键字。所以你不能用那个关键字打印!

    根据 Java 规范:

    使用关键字 super 的表单只在一个实例中有效 方法、实例初始值设定项或构造函数,或在 一个类的实例变量。如果它们出现在其他任何地方, 发生编译时错误。

    【讨论】:

    • 据我所知,它是一个对this 的对象引用,被强制转换为父类类型。我也不确定您引用的段落如何回答我的问题,因为我在实例方法中使用了 super。
    • super 不是普通对象,可以单独使用。超级不行。
    【解决方案2】:

    super 用法:

    1. 语句super()用于调用父构造函数和 只能从孩子的构造函数调用。它也必须是 子构造函数中的第一条语句。
    2. super.instance_variable
    3. super.instance_method

    例如:

    class Animal {
        String name;
        Animal() { }
    
        String myName() {
            return name;
        }
    }
    
    class Dog extends Animal {
    
        Dog() {
            super();
        }
    
        public String toString() {
            return "Test " + super.myName() + super.name;
        }
    }
    

    just super 没有独立用法。 this 引用当前对象,可以单独调用。

    【讨论】:

    • 我不是在谈论构造函数调用中的super(),而是在方法调用中使用"Test " + super。我不能在我的示例中使用this,因为它会导致无限递归。
    • just super 没有用处。
    • @DorianGray 你有两个答案,现在向你解释使用 super 是不可能的。真正的问题是:你的 toString 方法应该做什么?!
    • 嗯,它应该等同于上面例子中的"Test " + super.toString()
    【解决方案3】:

    关键字super 本身不是有效的Java 表达式。答案的总结是 super 在 Java 中根本就没有这样使用。

    以下类型的表达式是Java语法产生式,包括super,它们都没有单独出现super

    • Field Access Expressions

      • super . Identifier这个表单访问超类成员。

      • TypeName . super . Identifier 这个表单访问封闭类的超类成员。

    • Method Invocation Expressions

      • super . Identifier ( [ArgumentList] )这个表单调用一个超类方法。

      • TypeName . super . Identifier ( [ArgumentList] ) 此表单调用超接口方法或封闭类中的超类方法,具体取决于TypeName 是类名还是接口名。

    • Method Reference Expressions

      • super :: Identifier

      • TypeName . super :: [TypeArguments] Identifier

    相比之下,this 本身就是一个表达式,因为它本身允许形成一个primary expression。关键字super 本身不在此产品列表或子产品中。将“主要”视为表达式的基本构建块。

    初级:

       PrimaryNoNewArray

       ArrayCreationExpression

    PrimaryNoNewArray:

       字面量

       类文字

       this

       类型名称。 this

       ( 表达式)

       ClassInstanceCreationExpression

       字段访问

       数组访问

       方法调用

       方法参考

    this 关键字在表达式中起作用,因为它是一个 Primary,它可以参与更大、更复杂的涉及运算符的表达式,例如 +

    总而言之,super 仅涉及较大的产生式,以引用访问超类的特定方式。关键字this,虽然它可以参与更大的产生式,但它本身被允许作为主要表达式,这允许它使用运算符参与更复杂的表达式。

    【讨论】:

      【解决方案4】:

      简单:“super”不能这样用。

      该关键字可用于调用超级构造函数或引用超级方法/字段。但它不能“完全靠自己”。

      因为没有“超级”对象。您可以使用“this”来引用“this”对象,但没有“独立”超级对象。所以语言不允许你像使用“this”那样使用“super”。

      【讨论】:

      • 嗯,它不是一个独立的对象,但据我所知,它仅相当于将this 强制转换为父类类型,这会强制编译器调用父类方法。
      • @DorianGray 我建议你重新审视这个话题。要么您的来源有误,要么您误读了它。
      • 好吧,从 15.11.2 开始。使用 super 访问超类成员 super.Identifier 形式引用当前对象的名为 Identifier 的字段,但当前对象被视为当前类的超类的一个实例。我认为,“视为”与“投射到”几乎相同。此外,在下面的示例中还说明了::在类 T3 中,表达式 super.x 被视为:((T2)这个).x
      猜你喜欢
      • 1970-01-01
      • 2021-11-18
      • 2017-11-24
      • 2022-11-02
      • 2013-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多