Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is casting from Iterable<?> to Iterable<Object> always safe?

Is casting from Iterable<?> to Iterable<Object> always safe?

It looks like it is, since I can't see any way how to misuse it to produce an unexpected ClassCastException, but I guess I'm missing something.

like image 528
maaartinus Avatar asked Oct 17 '13 18:10

maaartinus


People also ask

What does unchecked cast mean Java?

2. What Does the “unchecked cast” Warning Mean? The “unchecked cast” is a compile-time warning. Simply put, we'll see this warning when casting a raw type to a parameterized type without type checking. An example can explain it straightforwardly.

Is Java Util list iterable?

util. Collection extends java. lang. Iterable , you don't have to do anything, it already is an Iterable.


2 Answers

In the case of Iterable, yes, since it doesn't have any methods that take a T, only methods that return a T (well, via its iterator). EDIT: See below.

Java doesn't have a formal concept of covariant classes vs contravariant classes, which is why it can't distinguish between an Iterable<T> and a List<T> (the latter of which is not safe to cast from List<?> to List<Object>). Since it doesn't have this distinction, it's forced to warn you that the cast is potentially unsafe. After all, unsafe doesn't mean things will break, it just means that the compiler can't guarantee that they won't.

EDIT: maaartinus found a good counterexample. The above is only true if the Iterable is immutable; but of course, immutable types are generally covariant anyway (even if Java doesn't recognize that, since it doesn't recognize immutability).

like image 125
yshavit Avatar answered Sep 23 '22 00:09

yshavit


Now I know what bothered me:

Integer blown() {
    List<Integer> intList = new ArrayList<Integer>();
    Iterable<?> iterable = intList;

    @SuppressWarnings("unchecked") // This cast should be safe, shouldn't it?
    Iterable<Object> objectIterable = (Iterable<Object>) iterable;
    safeMethod(objectIterable);

    return intList.get(0);
}

// This method is definitely fine, no unchecked cast.
private void safeMethod(Iterable<Object> objectIterable) {
    if (objectIterable instanceof List) {
        List<Object> list = (List<Object>) objectIterable;
        list.add("blown!");
    }
}

So the cast is safe as long you don't upcast and don't let the unsafe thingy escape.

like image 41
maaartinus Avatar answered Sep 23 '22 00:09

maaartinus