Reputation: 38645
Can someone explain to me why the following code does not work?
public class TestGeneric {
EntityManager entityManager = new EntityManager();
public <T extends Textable & Entity> void doAction(T obj) {
entityManager.getAliasForEntityClass(obj.getClass());
}
}
class EntityManager {
public String getAliasForEntityClass(Class<? extends Entity> clazz) {
return clazz.getCanonicalName();
}
}
interface Entity {
Long getId();
}
interface Textable {
String getText();
}
I'm getting the following error:
The method getAliasForEntityClass(Class<? extends Entity>) in the type EntityManager is not applicable for the arguments
(Class<capture#1-of ? extends Textable>)
If I wrote in this way, I did not have any error:
public class TestGeneric {
EntityManager entityManager = new EntityManager();
public <T extends Entity & Textable> void doAction(T obj) {
entityManager.getAliasForEntityClass(obj.getClass());
}
}
class EntityManager {
public String getAliasForEntityClass(Class<? extends Entity> clazz) {
return clazz.getCanonicalName();
}
}
interface Entity {
Long getId();
}
interface Textable {
String getText();
}
Template <T extends Entity & Textable>
and <T extends Textable & Entity>
means: T must implements Entity and Textable interfaces. Why position of interface so important in this example?
Upvotes: 3
Views: 1420
Reputation: 14025
The reason is that the erasure of T
is the leftmost type in the bound. From the getClass()
documentation:
The actual result type is
Class<? extends |X|>
where|X|
is the erasure of the static type of the expression on whichgetClass
is called.
The JLS specifies that "the erasure of a type variable is the erasure of its leftmost bound" (see here). So the type of obj.getClass()
is Class<? extends Textable>
in the first case and Class<? extends Entity>
in the other.
Upvotes: 2