This happens because of type erasure.
At runtime, generic type parameters don't exist.
Casting an object to a generic type parameter has no effect. (which is why you get the unchecked cast warning)
Therefore, your first line autoboxes 42
to Object
to pass to the method.
The function then returns that Object
, which is passed to System.out.println
.
Your second call calls the cast
method of the int
primitive type.
This throws an exception, because objects cannot be casted to primitive types. (auto-boxing is a purely compile-time feature, so it doesn't help)
The error happens when cast()
checks isInstance()
to verify that the cast is valid.
The docs for isInstance()
say:
Specifically, if this Class object represents a declared class, this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses); it returns false otherwise. If this Class object represents an array class, this method returns true if the specified Object argument can be converted to an object of the array class by an identity conversion or by a widening reference conversion; it returns false otherwise. If this Class object represents an interface, this method returns true if the class or any superclass of the specified Object argument implements this interface; it returns false otherwise. If this Class object represents a primitive type, this method returns false.
(emphasis added)
Your edit works because you are no longer using a primitive type.
In both cases, the compiler autoboxes 42
so that it can be passed as an object.
The first call, as before, has no effect.
The second call verifies that the boxed integer is in fact an instance of the Integer
class, then returns it.