Reputation: 26555
In some legacy code I found the following method:
public static <T> T cast(Object o) {return (T) o;}
This is used to cast arbitrary objects to any type only based on the return type like this:
List<SomeType> foo = cast(someObject);
How is that cast method able to cast to the correct type?
Upvotes: 2
Views: 53
Reputation: 106440
It isn't.
This is an unchecked cast, and will fail at runtime if the types you're trying to cast to don't align.
As a simple case, observe what happens when we attempt to use this method to cast a list of Integer
s to a list of BigInteger
s.
List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5);
List<BigInteger> bigIntList = cast(intList);
for(BigInteger i : bigIntList) {
System.out.println(i.doubleValue());
}
Or, for a less contrived but still broken cast, trying to cast simple types across.
Integer i = 10;
BigInteger bigI = cast(i);
System.out.println(bigI.doubleValue());
This legacy code is dangerously broken and should not be relied on for any kind of casting. In fact, the kind of casting that is desired from this should be handled by a transform method instead.
I should note - casting is you telling the Java compiler that you not only know what you're doing, but you're also accepting the risk if it fails, which is one reason why the compiler won't warn you about the invalid types. If this were done properly with generics (and I'm not entirely convinced it's possible with generics), then you would get a compile-time warning indicating what it is you were doing wrong.
Upvotes: 4
Reputation: 726639
The method does not do anything. The actual casting happens on the assignment.
Here is how you can see what is going on:
public static <T> T cast(Object o) {
try {
return (T) o;
} catch (ClassCastException cce) {
// This never gets printed
System.out.println("Cast has failed");
throw cce;
} finally {
System.out.println("Cast succeeded");
}
}
Now invoke the method with arguments that would cause the cast to throw:
List<SomeType> foo = cast(new Integer(5));
You will see the "Cast succeeded" printout, and then ClassCastException
would be thrown inside the method doing the call (demo).
The reason for this behavior is that Java implements generics using type erasure. If you would like to implement casting in a way that fails inside the method, pass Class<T>
as an additional argument:
public static <T> T cast(Object o, Class<T> cls) {
return cls.cast(o);
}
Upvotes: 4