从内部类继承

时间:2016-08-30 15:11:32

标签: java class oop

public class A {
    public A() {
        System.out.println("A()");
    }

    public class B {
        public B() {
            System.out.println("B()");
        }
    }
}
class Caller extends A.B {
    Caller(A a){
        a.super();
    }
}


public class Main {
    public static void main(String[] args) {
        Caller as= new Caller(new A());
    }
}

为什么我们需要在扩展内部类的类中调用a.super()?它在做什么?

没有a.super()程序不想编译。

Error:(48, 20) java: an enclosing instance that contains A.B is required

5 个答案:

答案 0 :(得分:5)

a.super() 不会调用A构造函数。由于A中的new A()表达式,Main.main()构造函数会运行。

a.super()调用nullary(和唯一)B构造函数,指定a作为对A的包含实例的引用,该实例作为内部的子类班级A.B,每个Caller必须有。

答案 1 :(得分:3)

答案是:因为这是在Java语言规范中指定的方式。

您的班级A.BA的内部班级。构造函数有一个类型为A的隐藏参数 - 封闭(外部类)实例。

您的班级A.B中已经包含Caller,它本身不是内部类。但是超类的构造函数需要这个隐藏的A实例 - 外部类实例。

在Java中传递此方法的方法是使用此a.super();语法。

Java语言规范在section 8.8.7.1中定义了这个:

  

合格的超类构造函数调用以 Primary开头   表达式 ExpressionName 。它们允许子类构造函数   显式指定新创建的对象立即封闭   关于直接超类的实例(第8.1.3节)。这可能是   当超类是内部类时必需。

答案 2 :(得分:0)

错误说明了一切。关于内部类(非静态嵌套的)的关键之一是它们可以访问其外部(封闭)实例。但内部类需要知道它属于哪个外部实例。此信息保存在我们无法访问的Outer this$0引用中,但仍需将其设置为某个点,并且该点是构造函数的代码。

这就是我们通过outer.new Inner()创建内部类实例的原因,如

Outer outerInstance= new Outer();
Outer.Inner innerInstance = outerInstance.new Outer.Inner();
//                          ^^^^^^^^^^^^^^^^^

由于这个原因,外部实例也被传递给Inner类构造函数(作为隐藏参数)。

既然你正在扩展内部类,这意味着你的类只会指定内部类,但这并不意味着它不再是 Inner 类型。

因此,由于Caller的实例也被视为A.B内部类(因为它扩展了它),您必须确保它将了解其外部实例(A类)。为了使你在我们班的构造函数中成为可能,你需要

  1. 拥有您班级的实例
  2. 调用内部超类A.B的构造函数,因此您可以让它在this$0变量中保存该外部类引用。
  3. 通过将A实例作为类构造函数Caller(A a)的参数传递来解决第一点。

    第二点与调用outerInstance.new Inner()的方式类似,但这次我们不能使用new关键字,因为我们不想创建Inner类的新对象。我们想调用超类构造函数中的代码来初始化当前对象(及其隐藏的this$0字段)。通常的方法是致电super()。只有可能有点奇怪的是,我们需要以某种方式让super()调用哪个外部实例包含一个。所以可能使其与outer.new Inner()语法类似,我们使用outer.super()语法,在您的情况下是

    a.super();
    

答案 3 :(得分:-1)

由于您的Caller类扩展了A.B,因此第一次调用Caller构造函数将成为A.B构造函数(即使您在代码中没有看到它) )。

因此a.super()不会调用A.B构造函数。

答案 4 :(得分:-2)

这不是a.super()调用A.B构造函数,而是Caller()构造函数隐式调用它,因为Caller extends A.B。只有在那之后才执行a.super()行。