【问题标题】:If only one object is created during inheritance then what is super keyword referencing to?如果在继承过程中只创建一个对象,那么 super 关键字引用的是什么?
【发布时间】:2021-07-08 07:26:03
【问题描述】:

在下面的代码中,super关键字指的是什么?

class A {
    int i1 = 10;
    A() {
        System.out.println("class A");
    }
}
class B extends A {
    int i2 = super.i1;
    B() {
        System.out.println("class B");
    }
}
class C extends B {
    int i3 = super.i2;
    
    public static void main(String args[]) {
        C c = new C();
        System.out.println(c.i3);
    }
}

如果没有创建超类的对象/实例,那么 super 关键字引用的是什么,因为它是一个引用变量并且应该引用超类实例?

【问题讨论】:

  • 只有一个对象,但它是C,也是B,也是A。 super();调用父类的构造函数
  • 这毫无意义。我的意思是,人们经常为了约定而写它,但它对 A 类没有影响。
  • 我怀疑你在这里需要超级。您可以删除 super 并获得相同的结果。
  • 如果你不在这里写super(),编译器会为你插入as described here,因为超类有零参数的构造函数。
  • @ArnauMas 它在其他类中没有真正的“效果”,也没有

标签: java object inheritance super


【解决方案1】:
 int i2 = super.i1; and int i2 = i1; both are same

因为 i1 从父类 A 继承到子类 B 明智的选择

int i3 = super.i2;  and int i3 = i2; both are same

Super 仅指 Parent 类。 当您创建 C 类的对象时,会创建一个对象 - C 的一个实例。

C 既是 B 的实例,也是 A 的实例,也是 Object 由于 C 同时是 B 的实例和 A 的实例,所以在构造函数中添加了一个 cal super() 来调用父类的构造函数 C 的构造函数调用 B 的构造函数,B 的构造函数调用 A 的构造函数

【讨论】:

  • 如果没有超类的对象,super()是否会从JVM加载的类中调用超类的构造函数?
  • 是的 super() 只是调用父类的构造函数来确保所有继承的父类的成员变量都被正确初始化
  • @mp3001 是的,只运行超类构造函数的代码不需要超类的实例。它也可以使用子类的实例来做到这一点,它确实有。
【解决方案2】:

请注意superthis 有点不同,因为super 不是主表达式。事实上,super 根本不是一个表达式。所以说super 本身引用 是没有意义的。请注意,您不能这样做:

SomeType foo = super;

做什么有意义,是这些(不是涉及super的所有内容的详尽列表):

  • super(...); 形式的超类构造函数调用
  • super.identifier 形式的字段访问
  • super.identifier(...) 形式的方法调用

那些形式都指代不同的东西,但是super这个词本身并没有单一的含义,除非你对“与超类有关的东西”感到满意。

特别是在这个问题中,您询问的是字段访问权限。这在语言规范的15.11.2 部分进行了描述。

super.Identifier 形式引用当前对象的名为Identifier 的字段,但当前对象被视为当前类的超类的一个实例。

对于i1,由于B继承自A,所以i1将引用同一个字段,即使您将当前对象视为B,所以您查看什么类并不重要当前对象为。无论是super.i1,还是this.i1,还是只是i1,都没有区别。当您在B重新声明 i1 时,差异会更加明显:

class A { 
    int i1 = 10;
}
class B extends A { 
    int i1 = 20; 
    int i2 = super.i1;
}

i2 将获得值 10,而不是 20,因为您将当前对象视为 A。请注意,在这种情况下,B 的实例有两个名为 i1 的字段,一个继承自 A,另一个在 B 中声明。查看对象“作为A”将让您看到继承自A 的对象,否则它会被隐藏。

【讨论】:

  • 感谢您的澄清。只是一个问题,如果没有 A 和 B 的对象并且没有继承构造函数,那么 super() 从哪里调用构造函数?
  • 那么 A 和 B 的实例只是因为调用了它们的每个超级构造函数而被创建?就像你说的,这些(A 和 B)实例实际上是 C 类的实例/对象,只是被视为 A 和 B 的实例,对吧?
  • @mp3001 我想我最后的评论可能让你感到困惑。我的意思是,如果你做了new B()(让我们先处理一层继承,这样更容易解释),那么就有B 的实例。如果B 的构造函数随后调用super()(它是隐式执行的),则不会创建新对象,并且A 的构造函数主体会被简单地执行。而且我认为您的困惑是:当没有 A 对象时,如何运行 A 的构造函数主体?好吧,事实是,我们确实有一个 B 对象,并且由于继承,B 对象 是一个 A 对象。
  • @mp3001 我没有说B 的实例在这里被“视为”A 的实例。我的那部分答案是关于super.Identifier 形式的字段访问,而不是关于构造函数调用。我什至不知道“被视为A 的实例”在构造函数调用的上下文中意味着什么。
  • 好的,请纠正我的错误,因为继承,B 的实例也是 A 的实例。如果 B 类型和 A 类型的引用引用同一个对象,比如B b = new B(); C c = b;,那么它们具有相同的字段和方法,唯一的区别在于两个类具有不同定义的相同字段。在这种情况下,b 和 c 引用的实例拥有自己的该字段的副本。
猜你喜欢
  • 2015-06-07
  • 2010-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多