【问题标题】:Just like superclass members, do superclass constructors form part of the subclass object state?就像超类成员一样,超类构造函数是否构成子类对象状态的一部分?
【发布时间】:2015-03-26 21:18:37
【问题描述】:

请允许我解释一下我的理解。

class P
{
    P()
    {
        System.out.println("hi "+this); 
       /*which object of P is currently executing this constructor? 
         Is "this" here object referenced by q or some other object?*/
    }
}
class Q extends P
{
    Q()
    {
        super();  
        /*constructor of superclass called on this object(referenced by q) */
    }
}
class R
{
    public static void main(String args[])
    {
        Q q = new Q(); //constructor Q() invoked on object referenced by q
    }
}

所以我的疑问是: 1. super() 在 P 的哪个对象上调用(因为不存在)。 2. P()中的“this”指的是什么?它和q是同一个对象吗?也就是说this=q?

【问题讨论】:

  • 如果你问super() 是否调用了它自己的超类的super(),那么答案是肯定的(直到超类是Object)。
  • 我已经编辑了我的问题。请重新检查
  • 两天前,你问了一个非常相似的问题。您一遍又一遍地坚持没有P 的实例(除非您在之前提出问题时将其称为A)。我和其他人解释说存在P 的实例,因为Q 的任何实例也是P 的实例。为什么你还坚持没有P 的实例?提问后你不看答案吗?
  • 这意味着多态在这里起作用......因为我们能够使用子类引用访问超类构造函数(这当然也是超类引用)?

标签: java oop inheritance nested subclass


【解决方案1】:

代码,包括ctors,没有定义“对象状态”。实例字段集。而且,在底层,子类实例确实包含其超类的private 字段,但javac 确保它们只能通过调用超类方法(包括ctors)直接或间接访问。


关于您更新的问题:

class Q extends P
{
    Q()
    {
        super();  /*constructor of superclass called on this object(referenced by q) */
    }
}

这里Q扩展了P,所以super()调用了P的ctor。在执行 P 的 ctor 期间,this 允许引用属于 P 的字段和方法及其超类型(例如,Object),带有访问修饰符施加的限制(我的意思是您只能访问 public 和 w / 限制 protected 和 'package-private' 子类型成员),但不限于 P 的子类型

关于“不能访问 P 的子类型”规则还有一个转折点:如果您从 P 的 ctor 调用 P 的一些非私有(可覆盖)方法,那么该方法很可能有一天会在 Q 或其他子类型中被覆盖,你突然开始调用一些无法预料的代码!所以,this 内的 P 确实允许显式引用 P 的子类型方法,但不允许引用 P 的子类型字段(尽管隐式 P 的字段可以通过 P 的子类型方法访问)。

举个例子——将下面代码中的f()private更改为'package-local'并通过下面的执行链Derived#Derived() -> Base#Base() -> Derived#f() -> NPE!见证NPE:

class Base {

    private Integer base = 1;

    Base() {
        f();
    }

    private void f() {
        System.out.println(base);
    }
}

class Derived extends Base {

    private Integer derived;

    Derived() {
        super();
        derived = 2;
        f();
    }

    private void f() {
        System.out.println(derived.intValue());
    }
}

【讨论】:

    【解决方案2】:

    构造函数不会继承给子类。并且使用super() 您可以调用超类构造函数。您不能从子类访问超类的私有变量/属性。此外,超类的私有成员也不会继承到它的子类。

    【讨论】:

      【解决方案3】:

      构造函数在 java 中不被继承。

      根据official Java tutorial

      子类继承所有成员(字段、方法和嵌套 类)来自其超类。构造函数不是成员,所以他们 不是子类继承的,而是超类的构造函数 可以从子类中调用。

      当您调用super() 时,您只需调用父构造函数,该构造函数可以访问它所属类的私有成员。

      至于你问题的更新版本:

      1. 如上所述,super() 只是调用父构造函数。它不会在任何对象上调用,因为构造函数不是类的成员。

      2. P 构造函数中的this 将引用正在构造的子类 (Q) 的实例。

      编辑: 关于 2。这可以通过在您的 main 方法中输出引用 q 来轻松验证。它应该与P 构造函数中的System.out.println(this) 调用完全相同。

      public class R
      {
          public static void main(String args[])
          {
              Q q = new Q(); //constructor Q() invoked on object referenced by q
              System.out.println(q);
          }
      }
      

      【讨论】:

      • 你提到 super() 可以访问私有实例成员。但是实例成员总是与对象相关联。那么当我们从构造函数访问实例成员时,我们访问的是哪个对象的实例成员?
      • @user3678484 访问私有实例成员的不是 super() - 它是父构造函数。然而,如果您从构造函数中调用虚拟(非私有)方法 - 调用将是多态的。由于私有方法不会被继承,因此对私有方法的调用将简单地从定义构造函数的类中调用该方法。希望这是有道理的......
      猜你喜欢
      • 2012-10-10
      • 1970-01-01
      • 1970-01-01
      • 2018-06-06
      • 2013-06-20
      • 1970-01-01
      • 2013-10-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多