4
import java.util.*;

// Let's define a self-referential type:
class SelfReferential<T extends SelfReferential<T>> {}

//A complete (i.e. not parameterized) subtype of SelfReferential:
class SubclassA extends SelfReferential<SubclassA> {}

//A partial (i.e. parameterized) subtype of SelfReferential:
class SubclassB<T extends SubclassB<T>> extends SelfReferential<T> {}

//Two complete subtypes of SubclassB
class SubclassB1 extends SubclassB<SubclassB1> {}    
class SubclassB2 extends SubclassB<SubclassB2> {}

//Now let's define a generic type over SelfReferential:
class Generic<T extends SelfReferential<T>> {}

//No problem creating a subtype for A, B1 or B2
class GenericA extends Generic<SubclassA> {}   
class GenericB1 extends Generic<SubclassB1> {}    
class GenericB2 extends Generic<SubclassB2> {}

//We can also defined a parameterize type for specific types extending SubclassB
class GenericB<T extends SubclassB<T>> extends Generic<T> {}

//However, it does not seem possible to define a non-parameterized subtype of Generic of ANY subtype of SublassB
//My goal is to provide a type alias for GenericB<? extends SubclassB<?>> to avoid 
//having to mention it everywhere in the code. This is like providing an alias for ArrayList<String> using 
class ArrayListOfString extends ArrayList<String> {}

//Unsucessful attempts:
//class GenericAnyB extends Generic<SubclassB> {} //ERROR: bound mismatch
//class GenericAnyB extends Generic<SubclassB<?>> {} //ERROR: bound mismatch
//class GenericAnyB extends Generic<? extends SubclassB<?>> {} //ERROR: invalid syntax: a supertype cannot specify any wildcard
//class GenericAnyB extends Generic<SubclassB<? extends SubclassB>> {} //ERROR: bound mismatch
//class GenericAnyB extends Generic<SubclassB<SubclassB<SubclassB<SubclassB<SubclassB<SubclassB>>>>>> {} // well...
//class GenericAnyB extends <T extends SubclassB<T>> Generic<T> {} //ERROR: this syntax is illegal

Bottom line, I can't specify the "reference cycle" in the extends clause.

Question: Is this a Java language limitation?

gawi
  • 13,940
  • 7
  • 42
  • 78

1 Answers1

1

You're right that this isn't possible, just like declaring a variable with a self referencing type is impossible without wildcards or raw types. You wouldn't be able to directly instantiate a SubclassB for the same reason that you can't use it as a bound without a self-referencing type parameter.

See this post for more discussion on this limitation: Self bound generic type with fluent interface and inheritance

The bottom line is that GenericAnyB would need to be generic itself to use SubclassB as a bound:

class GenericAnyB<T extends SubclassB<T>> extends Generic<T> { }

Which just adds an extra step in the hierarchy before anything is usable:

class GenericB1 extends GenericAnyB<SubclassB1> { }   
class GenericB2 extends GenericAnyB<SubclassB2> { }
Community
  • 1
  • 1
Paul Bellora
  • 54,340
  • 18
  • 130
  • 181