In Java when casting from an Object to other types, why does the second line produce a warning related to the cast, but the first one doesn\'t?
void a(Object o)
It's because the object won't really be checked for being a List<Integer>
at execution time due to type erasure. It'll really just be casting it to List
. For example:
List<String> strings = new ArrayList<String>();
strings.add("x");
Object o = strings;
// Warning, but will succeeed at execution time
List<Integer> integers = (List<Integer>) o;
Integer i = integers.get(0); // Bang!
See Angelika Langer's Java Generics FAQ for more info, particularly the type erasure section.
Jon's answer is the right one, but occasionally you can't get around that warning (like when you're working with a legacy API). In those cases you can suppress the warning like so:
@SuppressWarnings("unchecked")
List<Integer> list = (List<Integer>) someApiThatReturnsNonGenericList();
For clarity, let me slightly rewrite the examples...
I would say, the cruxial difference between:
void a(Object o) {
Integer i = (Integer) o;
...
}
and
void a(Object o) {
List<Integer> list = (List<Integer>) o;
...
}
is that, given that there is a type-error, the first cast will always immediately throw a RuntimeException (specifically, a ClassCastException) when executed.
While the second one might not -- as long as the input parameter o is any kind of List<?>
, execution will just proceed, in spite of an incorrect cast.
Whether the code will somewhere later throw an exception or not, depends upon what you do with the list.
But regardless, an Exception might not be thrown at the line where the cast was made, but somewhere else (which might be a difficult bug to trace down) or not at all.
That's what I understand, is the reason the compiler-designers considered a warning appropriate in the second case only.