EDIT: even more simple example:
public <T> void shouldBeAbleToGetClassOfT(T t) {
Class<T> tClass;
// OK, but shows "unchecked cast" warrning.
tClass = (Class<T>) t.getClass();
// Compilation error!
tClass = t.getClass();
}
Incompatible types.
Required: Class<T>
Found: Class<capture<? extends java.lang.Object>>
I am a little confused about the type erasure in the example below:
public static class Example<T> {
private final T t;
public Example(final T t) {
this.t = t;
}
public <U extends T> void test(Consumer<T> consumer, U u) {
// OK, but shows "unchecked cast" warrning.
consumer.accept((T) t.getClass().cast(u));
// OK, but shows "unchecked cast" warrning.
consumer.accept(((Class<T>)t.getClass()).cast(u));
// Compilation error!
consumer.accept(t.getClass().cast(u));
}
}
The error in question is:
Error:(21, 46) java: incompatible types: java.lang.Object cannot be converted to T
What exactly is happening here?
Is the .getClass()
return value erased? Why?
What is the best way to handle this error?
EDIT: here is a little more complex use case, more closely related to my problem:
public class A<T> {
private final T t;
public A(final T t) {
this.t = t;
}
public void printClass() {
// OK, but shows "unchecked cast" warrning.
B<T> b = new B<>((Class<T>) t.getClass());
// Compilation error!
B<T> b = new B<T>(t.getClass());
b.printClass();
}
}
public class B<T> {
private final Class<T> t;
public B(final Class<T> t) {
this.t = t;
}
public void printClass() {
System.out.println(t);
}
}
From the docs for
getClass
:The static type of
t
isT
, and the erasure of that isObject
. That means thatt.getClass()
has static typeClass<? extends Object>
, notClass<? extends T>
as you might expect.Since
t.getClass()
has static typeClass<? extends Object>
, the compiler only knows thatt.getClass().cast(u)
is anObject
, not aT
. That means you can't pass it toconsumer.accept
.