gpt4 book ai didi

java - 为什么内部类的子类需要封闭实例?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:43:01 27 4
gpt4 key购买 nike

考虑具有 InnerClass 的类 OuterClass

public class OuterClass {
class InnerClass {

}
}

第二个类,它试图扩展 OuterClassInnerClass

public class Clazz extends OuterClass.InnerClass {
public Clazz(OuterClass outerClass) {
outerClass.super();
}
}

到目前为止一切顺利,这段代码可以工作,编译器应该不会发出警告。

但我想了解 - 为什么有必要将其传递给 OuterClass 的构造函数引用?为什么有必要调用它的 super 构造函数?

我想了解为什么必须这样精确?

此外,考虑这个类(与之前的类无关),其中类 ApartmentsHallBuilding 类的内部类,它是Solution 内部(innerception)。

public class Solution {
public class Building {
public class Hall {
private BigDecimal square;

public Hall(BigDecimal square) {
this.square = square;
}
}

public class Apartments {
}
}
}

然后是top-level class试图扩展inner inner class Hall

class BigHall extends Solution.Building.Hall {
public BigHall(Solution.Building building, BigDecimal square)
{
building.super(square);
}
}

看看这个烂摊子。最后两个类也应该编译,但是你能帮我弄清楚吗,为什么 BigHall 类在扩展内部内部类 Hall 时确实需要传递给构造函数对 Building 对象的引用而不是解决方案对象?

如果您能提供 JLS 的报价,那就太好了!

最佳答案

你的 InnerClass 是一个 inner class .

An inner class is a nested class that is not explicitly or implicitly declared static.

内部类可能有封闭的实例

An instance i of a direct inner class C [your InnerClass] of a class or interface O [your OuterClass] is associated with an instance of O, known as the immediately enclosing instance of i.

只有在静态上下文中声明的内部类没有封闭实例。

An instance of an inner class I whose declaration occurs in a static context has no lexically enclosing instances.

您的示例的内部类不在静态上下文中,因此需要一个封闭实例。

Java Language Specification然后说

The constructor of a non-private inner member class implicitly declares, as the first formal parameter, a variable representing the immediately enclosing instance of the class

(如果您有兴趣,它会进一步详细说明原因)。换句话说,您的 InnerClass 构造函数确实看起来像

public InnerClass(OuterClass OuterClass.this){} // this is valid syntax for entirely different reasons

它期望类型为 OuterClass 的参数用作其封闭实例。子类化此 InnerClass 类型不会改变这一点,尤其是因为任何子类型都必须调用其父类(super class)型的超构造函数。

关于构造函数的主题,specification also states

If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.

很明显,如果没有参数,您的代码将无法运行

public class Clazz extends OuterClass.InnerClass {
public Clazz() {
// implicit super() invocation
}
}

super() 构造函数调用无效。在这种情况下,这是因为语法错误。但是这个想法是, super 构造函数期望代表封闭实例的形式参数的参数,但您没有提供。正确的语法是您已有的语法。让我们定义它。

multiple kinds of constructor invocations .你的

public Clazz(OuterClass outerClass) {
outerClass.super();
}

是一个合格的父类(super class)构造函数调用defined作为

Qualified superclass constructor invocations begin with a Primary expression or an ExpressionName. They allow a subclass constructor to explicitly specify the newly created object's immediately enclosing instance with respect to the direct superclass (§8.1.3). This may be necessary when the superclass is an inner class.

chapter去解释表达式是如何求值的

If the superclass constructor invocation is qualified, then the Primary expression or the ExpressionName immediately preceding ".super", p, is evaluated.
[...]

Otherwise, the result of this evaluation is the immediately enclosing instance of i with respect to S.

换句话说,outerClass 引用的对象成为您的 Clazz 实例所需的封闭实例


简单来说,忽略内部类的情况,您的示例可以归结为类似

public class Foo {}
public class Bar {
public Bar(Foo foo){}
}
public class SubBar extends Bar {
public SubBar(Foo foo) {
super(foo);
}
}

SubBar 必须满足需要 Foo 实例的 Bar super 构造函数。这与您的 Clazz 类型发生的事情相同,只是它的父类(super class)型的构造函数是隐式的。

关于java - 为什么内部类的子类需要封闭实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42094083/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com