java – 为什么一个类不能扩展一个静态的嵌套类呢?

前端之家收集整理的这篇文章主要介绍了java – 为什么一个类不能扩展一个静态的嵌套类呢?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这个班:
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将“依赖”本身,因为(每个§8.1.4 “Superclasses and Subclasses” of The Java Language Specification,Java SE 8 Edition)一个类直接依赖于“在它的扩展或者实现子句[…]中被提到的任何类型作为超类或超级接口名称的完全限定形式的限定符“.

但我不太明白这里的动机.什么是有问题的依赖性?这是否只是为了与InnerParent非静态(因此最终会包含本身的词汇封闭实例)的情况保持一致?

解决方法

这似乎是一个相当恶劣的角色,因为有一个与循环继承相关的 number of bugs,通常导致编译器中的无限循环,堆栈溢出和OOM.以下是一些可能提供一些洞察力的相关报价:

Bug 4326631

This example is not legal,and this is made clear in the forthcoming
2nd edition of the Java Language Specification. Classes simultaneously
related by both inheritance and enclosure are problematical,however
the original innerclasses whitepaper did not adequately address the issue,
nor did the pre-1.3 compilers implement a consistent policy. In JLS 2nd
edition,the rule against cyclic inheritance has been extended to prohibit
a class or interface from “depending” on itself,directly or indirectly.
A type depends not only on types that it extends or implements,but also on
types that serve as qualifiers within the names of those types.

Bug 6695838

The two class declarations are indeed cyclic; accordingly to JLS 8.1.4 we have that:

Foo depends on Foo$Intf (Foo$Intf appears in the implements clause of Foo)
Foo$Intf depends on Moo$Intf (Moo$Intf appears in the extends clause of Foo$Intf)
Foo$Intf depends on Foo (Foo appears as a qualifier in the extends clause of Foo$Intf)

For transitivity,we have that Foo depends on itself; as such the code should be rejected with a compile-time error.

Bug 8041994

Stepping back,the directly-depends relationship for classes and interfaces was introduced in JLS2 to clarify JLS1 and to cover superclasses/superinterfaces that are nested classes (e.g. A.B in the Description).

Bug 6660289

This problem is due to the order in which javac perform attribution of type-variable bounds wrt class attribution.

1) Attribution of class Outer<T extends Outer.Inner>
1a) Attribution of Outer triggers attribution of Outer’s type variable
2) Attribution of Outer.T
2a) Attribution of Outer.T triggers attribution of its declared bound
3) Attribution of class Outer.Inner<S extends T>
3a) Attribution of Outer.Inner triggers attribution of Outer.Inner’s type variable
4) Attribution of Outer.Inner<S>
4a) Attribution of Outer.Inner.S triggers attribution of its declared bound
5) Attribution of Outer.T – this does nothing but returning the type of T; as you can see,at this stage T’s bound has not been set yet on the object representing the type of T.

At a later point,for each attributed type variable,javac performs a check to ensure that the bound of a given type variable does not introduce cyclic inheritance. But we have seen that no bound is set for Outer.T; for this is the reason javac crashes with a NPE when trying to detect a cycle in the inheritance tree induced by the declared bound of Outer.Inner.S.

Bug 6663588

Type-variable bounds might refer to classes belonging to a cyclic inheritance tree which causes the resolution process to enter a loop when looking up for symbols.

对于你的具体问题“什么是有问题的依赖性”?它似乎是一个复杂的编译时符号解析边缘案例,JLS2中引入的解决方案是简单地禁止限定符类型以及实际超类引入的循环.

换句话说,理论上这可以使编译器得到适当的改进,但是直到有人出现并发生这种情况,才能在语言规范中禁止这种不寻常的关系.

猜你在找的Java相关文章