Reputation: 1235
Why first line in main does not throw ClassCastException while the second does?
import java.util.function.Function;
class Scratch {
static <T> T getSomething(Function<Integer, T> fun) {
return (T) fun;
}
public static void main(String[] args) {
Scratch.<String>getSomething(x -> "hello");
String something = Scratch.<String>getSomething(x -> "hello");
}
}
Upvotes: 3
Views: 86
Reputation: 140318
The difference is because you don't use the result of the method in the first case, but you do in the second.
A cast is an expression, but it's not a StatementExpression
. This means that you can't write this:
(String) somethingReturningAString();
but you can write:
String aString = (String) somethingReturningAString();
At compile time, the compiler inserts checkcast
instructions where it needs to, and where it can:
String
to a String
variable. As such, it checks the cast, and that fails.It's worth noting that there are some perhaps unexpected cases where a cast isn't strictly necessary, but is inserted. For example:
Scratch.<String>getSomething(x -> "hello").toString();
would fail with a ClassCastException
, since it would be transformed to:
((String) Scratch.getSomething(x -> "hello")).toString();
even though Object
has a toString()
method, and so it could invoke that without a cast.
Upvotes: 2
Reputation: 19926
Generics are only a compile time check (read about type erasure). So at runtime your getSomething()
method looks similar to this:
static Object getSomething(Function fun) {
return fun;
}
Now you see clearly that the first line will never throw an exception
Scratch.getSomething(x -> "hello");
because Function
is an Object
and thus can be returned without a problem.
The second line however will throw one, because it will look similar to this:
String something = (String) Scratch.getSomething(x -> "hello");
A Function
is still an Object
so it can be returned from the method, but it is not a String
and thus, you get your ClassCastException
.
The code compiles fine, because you instruct the compiler that you know what you're doing. You will get an Unchecked cast
warning though on this line:
return (T) fun;
This warning should be an indicator from the compiler to you, the programmer, that it (the compiler) can't be sure that that cast will succeed.
Upvotes: 1