Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you specify a generic type that subclasses another generic type _and_ a concrete interface?

Tags:

java

generics

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?

like image 458
Sled Avatar asked Nov 14 '13 17:11

Sled


People also ask

Can a generic type be an interface?

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.

Can an interface have a generic type Java?

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.

Can we use generic on interface in C#?

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.

Can generic types be inherited?

You cannot inherit a generic type. // class Derived20 : T {}// NO!


1 Answers

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.

like image 117
yshavit Avatar answered Nov 15 '22 18:11

yshavit