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();