Why can't a class extend a static nested class occurring within it?

ruakh

This class:

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

Fails to compile:

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

because OuterChild would "depend on" itself, because (per §8.1.4 "Superclasses and Subclasses" of The Java Language Specification, Java SE 8 Edition) a class directly depends on any type that "is mentioned in [its] extends or implements clause […] as a qualifier in the fully qualified form of a superclass or superinterface name."

But I don't really understand the motivation here. What is the problematic dependency? Is it just for consistency with the case where InnerParent were non-static (and would therefore end up with a lexically enclosing instance of itself)?

dimo414

This appears to be a fairly nefarious corner-case, as there are a number of bugs related to cyclic inheritance, often leading to infinite loops, stack overflows, and OOMs in the compiler. Here are some relevant quotes that may offer some insight:

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.

To your specific question of "what is the problematic dependency?" it appears to be a complex compile-time symbol resolution edge case, and the solution introduced in JLS2 was to simply ban cycles introduced by qualifier types as well as actual supertypes.

In other words this could theoretically be made to work with appropriate improvements to the compiler, but until someone comes along and makes that happen it's more practical to just ban this unusual relationship in the language specification.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Why can't an enum extend a class in Java?

From Dev

Why can't a class extend an enum?

From Dev

Why public class can't extend private class?

From Dev

Nested class AsyncTask can't modify Outer Class static objects

From Dev

Why an Outer Class Can’t Be Static?

From Dev

Why can't I use a private,internal,fileprivate method within a class/static method?

From Dev

Why can't I extend the Fixnum class in a module and use it?

From Dev

Why can't I extend the Fixnum class in a module and use it?

From Dev

Why can a static nested class appear to have instance fields?

From Dev

Why can't this top-level Groovy class be static?

From Dev

Why can't I declare and initialize static variable in inner class?

From Dev

Why can't we use this instance in the static method of extended class?

From Dev

Why I can't call a static method in another class?

From Dev

Why can’t this static inner class call a non-static method on its outer class?

From Dev

Why nested class can not be used as class for Filter

From Dev

Can't extend a compiled at runtime class

From Dev

Why can't I instantiate an empty array of a nested class?

From Dev

Can GSON handle static private nested class

From Dev

Can a static nested class be used as jsp bean?

From Dev

Can a static nested class be used as jsp bean?

From Dev

Can audio be implemented in a static nested class?

From Dev

Why does the nested class in a ConfigurationProperties class need to be static?

From Dev

Why a variable can be static but can not be global in class

From Dev

Why can´t I create a class object within a method from a different class in Java?

From Dev

Static objects of nested class can be declared without class definition

From Dev

Why can't I statically reference an inner class's static method on a generic class?

From Dev

Why static fields can't be accessed in class where was created on by specifying the class name

From Dev

Why can't I extend an interface "generic method" and narrow its type to my inherited interface "class generic"?

From Dev

Why a nested class can't have a member the type of which is the one of the enclosing class?

Related Related

  1. 1

    Why can't an enum extend a class in Java?

  2. 2

    Why can't a class extend an enum?

  3. 3

    Why public class can't extend private class?

  4. 4

    Nested class AsyncTask can't modify Outer Class static objects

  5. 5

    Why an Outer Class Can’t Be Static?

  6. 6

    Why can't I use a private,internal,fileprivate method within a class/static method?

  7. 7

    Why can't I extend the Fixnum class in a module and use it?

  8. 8

    Why can't I extend the Fixnum class in a module and use it?

  9. 9

    Why can a static nested class appear to have instance fields?

  10. 10

    Why can't this top-level Groovy class be static?

  11. 11

    Why can't I declare and initialize static variable in inner class?

  12. 12

    Why can't we use this instance in the static method of extended class?

  13. 13

    Why I can't call a static method in another class?

  14. 14

    Why can’t this static inner class call a non-static method on its outer class?

  15. 15

    Why nested class can not be used as class for Filter

  16. 16

    Can't extend a compiled at runtime class

  17. 17

    Why can't I instantiate an empty array of a nested class?

  18. 18

    Can GSON handle static private nested class

  19. 19

    Can a static nested class be used as jsp bean?

  20. 20

    Can a static nested class be used as jsp bean?

  21. 21

    Can audio be implemented in a static nested class?

  22. 22

    Why does the nested class in a ConfigurationProperties class need to be static?

  23. 23

    Why a variable can be static but can not be global in class

  24. 24

    Why can´t I create a class object within a method from a different class in Java?

  25. 25

    Static objects of nested class can be declared without class definition

  26. 26

    Why can't I statically reference an inner class's static method on a generic class?

  27. 27

    Why static fields can't be accessed in class where was created on by specifying the class name

  28. 28

    Why can't I extend an interface "generic method" and narrow its type to my inherited interface "class generic"?

  29. 29

    Why a nested class can't have a member the type of which is the one of the enclosing class?

HotTag

Archive