Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从内部类继承_Java_Class_Oop - Fatal编程技术网

Java 从内部类继承

Java 从内部类继承,java,class,oop,Java,Class,Oop,为什么我们需要a.super()调用扩展内部类的类?它在做什么 没有a.super()程序不想编译 public class A { public A() { System.out.println("A()"); } public class B { public B() { System.out.println("B()"); } } } class Caller extends A.B

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

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

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.B
,因此
调用方
构造函数的第一个调用将是
A.B
构造函数(即使您在代码中没有看到它)

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

它不是
a.super()
调用
a.B
构造函数,而是
调用方()
构造函数隐式调用它,因为
调用方扩展了a.B
。仅在此之后执行
a.super()
行。

a.super()
不会调用
a
构造函数。
A
构造函数作为
Main.Main()
中表达式
newa()
的结果运行


a.super()
调用空(且仅)
B
构造函数,指定
a
作为对
a
的包含实例的引用,该实例作为内部类
a.B
的子类,每个
调用者都必须有。

答案是:因为Java语言规范中就是这样指定的

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

在类
Caller
中有子类
A.B
,它本身不是内部类。但是超类的构造函数需要
A
的这个隐藏实例——外部类实例

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

Java语言规范定义如下:

限定的超类构造函数调用从主类开始 表达式或表达式名称。它们允许子类构造函数 显式指定新创建的对象的直接封闭 关于直接超类的实例(§8.1.3)。这可能是 当超类是内部类时,这是必需的


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

这就是为什么我们要通过
outer.new internal()
like创建内部类实例

Error:(48, 20) java: an enclosing instance that contains A.B is required
由于这个原因,外部实例也被传递给内部类构造函数(作为隐藏参数)

既然您正在扩展内部类,这意味着您的类将只指定内部类,但这并不意味着它不再是
internal
类型

因此,由于
调用方的实例
也被视为
A.B
内部类(因为它扩展了它),所以您必须确保它了解其外部实例(属于
A
类)。为了使您在我们类的构造函数中实现这一点,您需要

  • 有你们班的例子吗
  • 调用内部超类的构造函数
    A.B
    ,这样就可以让它将外部类引用保存在
    这个$0
    变量中
  • 通过将实例作为类构造函数
    调用方(A)
    的参数传递,可以解决第一点

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

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

    为什么a.super()什么都不做?没有
    a.super
    程序就不想编译。因为原始问题更改而被否决总是很有趣的,对吗@Scadge?你说
    a.super()
    没有调用超类构造函数
    a.B
    ,这是错误的,因为
    a.super()
    调用超类构造函数
    A.B
    ,并将外部类实例传递给它。这个问题在这个问题的第一个版本中。所以我不认为问题的改变对你答案的准确性有任何影响。这个问题没有一个版本的答案是正确的。毫无疑问,这是Java.Nope中一些真正奇怪的边缘语法
    调用方
    扩展了
    A.B
    ,而不是
    A
    ,因此其构造函数调用
    A.B
    ,而不是
    A
    的构造函数
    A.B
    扩展了
    对象
    ,因此其构造函数也不会调用
    A
    的构造函数
    a.super()
    事实上调用了
    a.B
    @JohnBollinger的构造函数,我不是说
    Caller()
    调用了
    a
    的构造函数,请再次阅读我的答案。另外,最初的问题是“为什么
    a.super()
    调用
    a.B
    constructor”,我的回答解释说它不调用@Scadge,但它调用了,这就是为什么你的答案是错误的。Adam Rosini的答案也是一样,在封闭类之外扩展内部类是一种非常糟糕的代码设计。你应该重新考虑设计。编辑问题而不提及问题本身也不太好。添加不完整的
    C
    声明的目的是什么?这和这个问题没有任何关系。我把编辑的内容往后推了推。花了
    a.super();