I'm reading J. Bloch's effective Java and now I'm at the arrays vs lists section. Here is an example of unchecked cast he provided:
interface Function<T> {
T apply(T arg1, T arg2);
}
public class Main{
public static void main( String[] args ){
Function<String> f = null;
List<String> str = Arrays.asList("asd");
//staff
reduce(str, f, ""); //E's deduced to String. Where is type-unsafe?
}
static <E> E reduce(List<E> list, Function<E> f, E initVal) {
E[] snapshot = (E[]) list.toArray(); // Unchecked cast
E result = initVal;
for (E e : snapshot)
result = f.apply(result, e);
return result;
}
}
He said that the method is not type-safe and we can easily get the ClassCastException
. But I don't see how. Where's the type-unsafe, the type variable E
will always be deduced to the appropriate type so we're no worried about class-cast-exeption.
Couldn't you give an example with throwing ClassCastException
?
If we can't eliminate the “unchecked cast” warning and we're sure that the code provoking the warning is typesafe, we can suppress the warning using the SuppressWarnings(“unchecked”) annotation. When we use the @SuppressWarning(“unchecked”) annotation, we should always put it on the smallest scope possible.
Unchecked cast means that you are (implicitly or explicitly) casting from a generic type to a nonqualified type or the other way around.
An unchecked warning tells a programmer that a cast may cause a program to throw an exception somewhere else. Suppressing the warning with @SuppressWarnings("unchecked") tells the compiler that the programmer believes the code to be safe and won't cause unexpected exceptions.
Adding @Suppress("UNCHECKED_CAST") (also possible through IDEA's Alt + Enter menu) to any of statement, function, class and file should help.
There's no compile-time guarantee that list.toArray()
will return the array of type E[]
. Moreover it almost always returns an array of type Object[]
. Thus depending on the later usage of this array you may have a ClassCastException
. For example, consider the following code:
public static void main( String[] args ){
List<String> str = Collections.singletonList("asd");
String[] array = test(str);
}
static <E> E[] test(List<E> list) {
E[] snapshot = (E[]) list.toArray(); // Unchecked cast
return snapshot;
}
Here you return this E[]
array and the receiver expects that String[]
array is returned. But actually it's Object[]
array, thus you will get the ClassCastException
in main
method after the returned generic type is implicitly cast to the String[]
.
In your code you can be sure that the array is used in safe way. But compiler is not smart enough to make this analysis, so it just warns you.
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