The following code is from an Android library called ButterKnife. I'm figuring out how it works.
@SuppressWarnings("unchecked") // That's the point.
public <T> T castParam(Object value, String from, int fromPosition, String to, int toPosition) {
try {
return (T) value;
} catch (ClassCastException e) {
throw new IllegalStateException("Parameter #"
+ (fromPosition + 1)
+ " of method '"
+ from
+ "' was of the wrong type for parameter #"
+ (toPosition + 1)
+ " of method '"
+ to
+ "'. See cause for more info.", e);
}
}
I tried to recreate the behaviour of this function:
@SuppressWarnings("unchecked")
public static <T> T cast(Object o){
try {
return (T) o;
} catch (ClassCastException e){
throw new AssertionError("Error");
}
}
And usage:
Object o = new String("test");
Double d = cast(o);
But the exception is not never caught, it gets thrown at the line when the method is called. Why is that?
Also, how does this work exactly? How does the method know what to cast to?
Generics types are checked at compile time only, due to type erasure. This is done because there was no way to introduce generics in the runtime in Java 5 without breaking backwards compatibility and forcing to recompile all the already existing libraries.
Long history short, when you define a "generic" class or method, the actual code is compiled as Object
instead of the type you are binding the method. All the checks of types are done at compile time.
So, your method code is not actually doing a cast in the return
statement, since it is assigning something (a String
) to an Object
return value. The actual ClassCastException is returned by the calling line because it is the place when the reference variable is actually typed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With