In such a function:
<T> void foo(T obj)
The type of obj.getClass()
is Class<?>
and not Class<? extends T>
. Why?
The following code works fine:
String foo = "";
Class<? extends String> fooClass = foo.getClass();
So the signature of T#getClass()
seems to return a Class<? extends T>
, right?
Why is the signature different if T
really is a generic?
To overcome the problem (and to make it more clear what I wander about), I have implemented this function:
@SuppressWarnings("unchecked") static <T> Class<? extends T> classOf(T obj) {
return (Class<? extends T>) obj.getClass();
}
Again the question: Why is the cast needed here and not in the String
case? And why is the
SuppressWarnings
needed? Isn't it always clear from the code that it will always be able to safely do this cast?
Is there any way I can get a Class<? extends T>
from obj
? If yes, how? If not, why not?
One way would be to use classOf
. That would be safe, right? If that is always safe and gives a safe way to really get a Class<? extends T>
(instead of a Class<?>
), why is there no such function in Java? Or is there?
How about that case:
<T> void bar(T[] array)
array.getClass().getComponentType()
again returns a Class<?>
and not a Class<? extends T>
. Why?
I have implemented this function:
@SuppressWarnings("unchecked") static <T> Class<? extends T> classOf(T[] array) {
return (Class<? extends T>) array.getClass().getComponentType();
}
Is this again safe to use?
To clarify more what I wonder about. Consider this demo code:
static interface I<T> {
Class<? extends T> myClass();
}
static class A implements I<A> {
public Class<? extends A> myClass() {
return this.getClass();
}
}
static <T> void foo(I<T> obj) {
Class<? extends T> clazz = obj.myClass(); // this works
}
This works fine. But the same does not for Object#getClass()
.
Why wasn't it possible for example to have a generic interface like ClassInstance<T>
with the function getClass()
and every Java Object automatically implementing this? This would have exactly those improvements I am talking about over the solution to have it extending from a non-generic base class Object
.
Or having Object
as a generic class:
static abstract class Object<T> {
abstract Class<? extends T> myClass();
}
static class B extends Object<B> {
public Class<? extends B> myClass() {
return this.getClass();
}
}
static <T> void bar(Object<T> obj) {
Class<? extends T> clazz = obj.myClass(); // this works
}
Now think of myClass()
as getClass()
and think about that the compiler would automatically add that to every class. It would have resolved a lot of those casting issues.
The main question I am talking about is: Why wasn't it made like this?
Or to put it again in different words: Here, I describe in more detail the solution of such classOf
function which overcomes the problem. Why wasn't it made like this, i.e. why is the original function not like this?
(I don't really want to get an answer like: the way Java works right now, i.e. extending from a non-generic Object
which defines this function, makes this not possible. I am asking why it wasn't solved somehow differently so that it would have been possible.)