I have a family of domain models, each of which has a subclass that extends it and implements a specific interface, like this (Cloneable
is not the interface in question, it's for example purposes only):
class A{}
class B extends A implements Cloneable{}
class C{}
class D extends C implements Cloneable{}
I want to create a generic type signature that will enforce this pairing, I've tried this which FAILS:
<T1,T2 extends T1 & Cloneable> void f ( T1 t1, T2 t2 ){}
but I get message in my IntelliJ IDE "Type parameter cannot be followed by other bounds"
; it still FAILS if I switch the order around to:
<T1,T2 extends Cloneable & T1> void f ( T1 t1, T2 t2 ){}
I get the message "Interface expected here."
Confusingly, both of these signatures WORK:
<T extends A & Cloneable> void f( A a, T t ){}
<T1,T2 extends T1> void f ( T1 t1, T2 t2 ){}
Is this just a weird limitation of Java's generic type system that I cannot have a generic class (ie T2
) extend both another generic class (ie T1
) and a concrete interface (eg Cloneable
)?
tl;dr: So, why won't <T1,T2 extends Cloneable & T1> void f ( T1 t1, T2 t2 ){}
compile: is it a limitation of the Java generic syntax or am I using the wrong syntax?
Generic Interfaces in Java are the interfaces that deal with abstract data types. Interface help in the independent manipulation of java collections from representation details. They are used to achieving multiple inheritance in java forming hierarchies.
Java Generic Interface In similar way, we can create generic interfaces in java. We can also have multiple type parameters as in Map interface. Again we can provide parameterized value to a parameterized type also, for example new HashMap<String, List<String>>(); is valid.
You can declare variant generic interfaces by using the in and out keywords for generic type parameters. ref , in , and out parameters in C# cannot be variant. Value types also do not support variance. You can declare a generic type parameter covariant by using the out keyword.
You cannot inherit a generic type. // class Derived20 : T {}// NO!
The answer is in JLS 4.4:
TypeParameter:
TypeVariable TypeBoundopt
TypeBound:
extends TypeVariable
extends ClassOrInterfaceType AdditionalBoundListopt
AdditionalBoundList:
AdditionalBound AdditionalBoundList
AdditionalBound
AdditionalBound:
& InterfaceType
The & Cloneable
is an AdditionalBound, which can only be used in an AdditionalBoundList. An AdditionalBoundList can only be used after ClassOrInterfaceType. And T1
is a TypeVariable, not a ClassOrInterfaceType.
So, yes, it's a limitation of the Java generic syntax.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With