当前位置: 首页 > 面试题库 >

为什么类不能扩展其中发生的静态嵌套类?

颛孙博易
2023-03-14
问题内容

这节课:

public class OuterChild extends OuterChild.InnerParent {
    public static class InnerParent {
    }
}

无法编译:

$ javac OuterChild.java
OuterChild.java:1: error: cyclic inheritance involving OuterChild
public class OuterChild extends OuterChild.InnerParent {
       ^
1 error

因为OuterChild
根据Java语言规范

Java SE 8 Edition


8.1.4节“超类和子类”)类将直接依赖于“本身”,因为类直接取决于“
[其] extendsimplements子句[…中提到的”的任何类型。 ]作为超类或超接口名称的完全限定形式的限定符。”

但是我真的不明白这里的动机。什么是有问题的依赖关系?是否只是为了与InnerParent非语言环境保持一致static(因此最终将以其自身的词汇包围实例)?


问题答案:

这似乎是一个非常有害的极端情况,因为存在许多与循环继承相关的错误,这些错误通常导致编译器中出现无限循环,堆栈溢出和OOM。以下是一些可能提供一些见解的相关报价:

错误4326631:

这个例子是
合法的,在即将出版的第二版Java语言规范中对此做了明确说明。通过继承和封闭性同时关联的类是有问题的,但是原始的内部类白皮书并未充分解决该问题,1.3之前的编译器也未实施一致的策略。在JLS
2nd
Edition中,扩展了禁止循环继承的规则,以禁止类或接口直接或间接“依赖”自身。一个类型不仅取决于它扩展或实现的类型,还取决于那些类型名称中充当限定符的类型。

错误6695838:

这两个类的声明确实是循环的。根据JLS 8.1.4,我们有:

Foo取决于Foo $ Intf(Foo $ Intf出现在Foo的Implements子句中)
Foo $ Intf取决于Moo $ Intf(Moo $ Intf出现在Foo $ Intf的extends子句中)
Foo $ Intf取决于Foo(Foo出现为Foo $ Intf的extends子句中的限定符)

对于传递性,我们认为Foo依赖于自身。因此,应使用编译时错误拒绝该代码。

错误8041994:

退后一步,在JLS2中引入了类和接口的直接依赖关系,以阐明JLS1并涵盖嵌套类的超类/超接口(例如,描述中的AB)。

错误6660289:

此问题归因于javac执行wrt类归因的类型变量范围归因的顺序。

1)类Outer
1a)属性Outer的属性触发了属性类型变量的
属性2)属性Outer.T的
属性2a)属性Outer.T的属性触发了声明的绑定的
属性3)属性类别Outer的属性触发了.Inner
3a)Outer的归属.Inner触发Outer.Inner的类型变量的
归属4)Outer.Inner
归属4a)Outer.Inner.S的归属触发其声明的绑定的归属
5)归属of Outer.T-除了返回T的类型外什么也不做;如您所见,在此阶段,尚未在表示T类型的对象上设置T的界限。

稍后,对于每个属性类型变量,javac都会执行检查以确保给定类型变量的边界不会引入循环继承。但是我们已经看到,Outer.T没有设置任何限制。因此,这是javac在尝试检测由Outer.Inner.S的已声明边界引起的继承树中的循环时因NPE崩溃的原因。

错误6663588:

类型变量界限可能是指属于循环继承树的类,当查询符号时,此类会导致解析过程进入循环。

对于您的“ 问题依赖性是什么?
”这个特定问题,这似乎是一个复杂的编译时符号解析边缘情况,并且JLS2中引入的解决方案是简单地禁止限定符类型以及实际超类型引入的循环。

换句话说,从理论上讲,可以对编译器进行适当的改进,但是直到有人出现并实现这种情况时,在语言规范中禁止这种不寻常的关系才更实际。



 类似资料:
  • 问题内容: 我正在查看Java代码,并注意到它使用了静态嵌套类。 使用静态嵌套类而不是普通内部类的原因是什么? 我能想到的唯一原因是Entry不能访问实例变量,因此从OOP的角度来看,它具有更好的封装性。 但是我认为可能还有其他原因,也许是性能。可能是什么? 注意。我希望我的术语正确,可以将其称为静态内部类,但是我认为这是错误的:http : //java.sun.com/docs/books/t

  • 问题内容: 什么是静态嵌套类?静态和非静态嵌套类有什么区别? 问题答案: 静态内部类是嵌套在具有修饰符的另一个类中的类。除了可以访问在其内部定义的类的私有成员之外,它与顶级类几乎相同。 类是静态内部类。类是一个非静态的内部类。两者之间的区别是,非静态内部类的实例被永久连接到的实例-你不能创建一个没有。不过,您可以独立创建对象。 中的代码,并且都可以访问x; 不允许使用其他代码。

  • 问题内容: 我想知道为什么在Java语言中a 不能扩展。 我不是在谈论一个延伸的(这不能做,因为Java没有多重继承,而Š隐含延长),但一类的以只添加额外的方法,而不是额外的枚举值。 就像是: 要这样使用: 因此,有人可以对此限制提供理由(或将我指向正确的JLS部分)吗? 问题答案: 我认为 他们这样做 的答案来自以下问题: 在您的示例中,如何实例化MyClass?用户永远不会(通过)显式实例化枚

  • 为什么我不能这样做/是否有解决方法来实现这一点: 这两个编译错误是 > On

  • 但是为什么在下面的情景中允许静态嵌套类对象的实例化呢? 为什么我们可以创建内部类的对象,如果它被标记为静态的?

  • 问题内容: 我已经开始学习用于Android应用程序开发的Java语言。 根据我对静态类的理解,我们无法实例化静态类的对象。 但是,为什么在随后的情况下允许实例化静态嵌套类对象? 如果将内部类的对象标记为静态,为什么我们可以创建它呢? 问题答案: 根据我对静态类的理解,我们无法实例化静态类的对象。 您对“静态类”的含义的理解不正确。基本上, Java中 的“静态类” 是嵌套类,它没有对包含类的实例