不会将toString()方法中的super关键字隐式转换为super.toString()

时间:2018-06-20 04:56:34

标签: java inheritance

我有以下两个类别,如下所示。为了简单起见, 仅显示toString重写的方法。

        public class Circle {
        @Override
            public String toString() {
                return "Circle";
            }
        }
        public class Cylinder extends Circle {
            @Override
            public String toString() {
     //     return "Cylinder"+this;  // runs without explicitly calling toString() on this keyword
     //     return "Cylinder"+super;  // throws error, asks to delete super token
            return "Cylinder["+super.toString(); // runs without error after adding .toString() with super keyword
            }

}

我遇到的问题是我对super关键字的理解。 super关键字的toString()应该像该关键字一样隐式调用。实际上,大多数教程和书籍都将super关键字称为对super类的一种对象引用。因此,在toString()中与“ +”串联运算符一起使用时,它的行为必须与此关键字相同。请帮助我理解这一点。

4 个答案:

答案 0 :(得分:4)

this 不同,Java中的 super 关键字不是对象引用。

用作对调用对象的引用。

但是,没有参考ID可以存储在 super super 是用于解析父类,其方法和数据成员的关键字。

因此,您无法打印 super 关键字的值。您只能使用 super 关键字访问父类的方法和成员。

this

super

Expressions

答案 1 :(得分:2)

在Java中,super关键字在两个地方使用。

  1. 子类的构造函数。
  2. 在子类的重写方法中。

在构造函数中使用时,必须在第一行调用super()。如果要调用另一个构造函数重载,则也必须在该构造函数的第一行调用this()

如果父对象也具有默认构造函数,则不带参数的构造函数(即默认构造函数)无需调用super()。这是因为编译器实际上是为您完成的,因此它仍然存在。

在重写的方法中使用时,您正在调用该方法的父实现。您不能调用super(),因为那是给父构造函数的。您通过super.foo()致电。与super()不同,您必须显式调用它。如果您重写一个方法并实现为空,则该方法将不执行任何操作。

此外,super.foo()不仅可以用在覆盖方法中。此外,您不必调用与要覆盖的方法相同的方法。例如,这是允许的:

public void foo() {
    System.out.println(super.toString());
}

尽管允许这样做,但在这种情况下更常见的是调用this.toString()。如果您的类已覆盖toString()并且您确实想要原始实现,则可以使用此方法。

最后,super关键字不能单独使用。它始终采用super()super.method()的形式。

示例:

public class Base {
    @Override public String toString() {
        return "Base";
    }
}

public class Sub extends Base {
    public void foo() {
        System.out.println(super.toString());
        System.out.println(this.toString());
    }

    @Override public String toString() {
        return "Sub";
    }
}

public class Test {
    public static void main(String[] args) {
        Sub sub = new Sub();
        sub.foo();
    }
}

输出:

Base
Sub

答案 2 :(得分:2)

路易斯在评论super中提到的不是正常对象。这是特例。

根据java spec

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

答案 3 :(得分:1)

根据Java语言规范§15.11.2和§15.12.1,

  

使用super

访问超类成员      

格式super.Identifier指的是   当前对象,但将当前对象视为的实例   当前类的超类。

     

格式Identifier指的是名为T.super.Identifier的字段   与Identifier对应的词汇包围实例,但是带有   实例被视为T的超类的实例。

     

...

     

编译时步骤1:确定要搜索的类或接口(在方法调用表达式中)

     

如果格式为T,则要搜索的类是其声明包含方法调用的类的超类。

它仅提及super.[TypeArguments]Identifier表达式的两种形式-supersuper.Identifier。您没有使用这两种形式。您正在使用T.super.Identifier,就好像它是super,就好像它是可以自己使用的某种变量一样。这不是事实,this的行为与super完全不同。

如果您比较规范如何描述this

  

§15.8.3this

     

关键字this仅可在以下情况下使用:

     
      
  • 在实例方法或默认方法(第8.4.7节,第9.4.3节)的正文中
  •   
  • 在类的构造函数的主体中(第8.8.7节)
  •   
  • 在类的实例初始化器中(第8.6节)
  •   
  • 在一个类的实例变量的初始化器中(第8.3.2节)
  •   
  • 表示接收方参数(第8.4.1节)
  •   

如您所见,这意味着this可以单独使用。 this不能。

此外,像super这样的表达式比"Cylinder"+super的可读性差。你不觉得吗顺便说一下,"Cylinder"+suer.toString()可能会导致无限递归。