erotsppa
erotsppa

Reputation: 15031

How come .getClass forces me to use extends?

I have a method

public static <T, U extends T> void method(T source, T destination, Class<U> class){}

works fine with

O.method(string1, string2, string1.getClass());

But if I change the method to

public static <T> void method(T source, T destination, Class<T> myclass){}

it won't compile. Why?

Upvotes: 0

Views: 50

Answers (2)

newacct
newacct

Reputation: 122449

The type of the result of .getClass() is Class<? extends |X|>, where |X| is the erasure of the type of the expression that .getClass() is called on. The reason for the ? extends wildcard is that an object of a subclass of X can be pointed to by a variable or value of type X, and therefore, when you run .getClass(), the class that is returned might be a subclass.

Assuming the variable string1 is of type String, string1.getClass() has type Class<? extends String>, and the argument types String, String, Class<? extends String> are not compatible with your second signature, but is compatible with your first. (Though arguably the generics in your first signature are unnecessary, because T and U can always be chosen to be Object, and it wouldn't accept any fewer arguments.)

Of course, we know that the class String is final, so Class<? extends String> is the same as Class<String>, but the type system does not take that into consideration. Since you know string1 is type String, which is final, you can just replace that with String.class directly.

Upvotes: 0

Vinay Prajapati
Vinay Prajapati

Reputation: 7504

object.getClass() returns Class<?> type where ? is any type. Hence, for any class you can't determine the type of returned class.

More to understand below is the documentation comment of getClass method

 /**
     * Returns the runtime class of this {@code Object}. The returned
     * {@code Class} object is the object that is locked by {@code
     * static synchronized} methods of the represented class.
     *
     * <p><b>The actual result type is {@code Class<? extends |X|>}
     * where {@code |X|} is the erasure of the static type of the
     * expression on which {@code getClass} is called.</b> For
     * example, no cast is required in this code fragment:</p>
     *
     * <p>
     * {@code Number n = 0;                             }
     * {@code Class<? extends Number> c = n.getClass(); }
     * </p>
     *
     * @return The {@code Class} object that represents the runtime
     *         class of this object.
     * @jls 15.8.2 Class Literals
     */

More importantly focus on The actual result type is {@code Class<? extends |X|>} where {@code |X|} is the erasure of the static type of the expression on which {@code getClass} is called. line from documentation comment.

Upvotes: 1

Related Questions