从Iterable <?>到Iterable <Object>的转换是否总是安全的?

maa*_*nus 8 java generics casting

从铸造Iterable<?>Iterable<Object>永远安全吗?

它看起来像是,因为我看不出任何方式如何滥用它产生意外ClassCastException,但我想我错过了什么.

ysh*_*vit 6

在是的情况下Iterable,是的,因为它没有任何方法可以采用a T,只返回一个方法T(通过它的迭代器).编辑:见下文.

Java没有协变类和逆变类的正式概念,这就是为什么它无法区分a Iterable<T>和a List<T>(后者不能安全地转换List<?>List<Object>).由于它没有这种区别,它被迫警告你,演员阵容可能不安全.毕竟,不安全并不意味着事情破裂,它只是意味着编译器不能保证它们不会.

编辑: maaartinus发现了一个很好的反例.只有Iterable是不可变的,上面才是真的; 但是,无论如何,不​​可变类型通常是协变的(即使Java不承认,因为它不能识别不变性).


maa*_*nus 4

现在我知道是什么困扰了我:

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!");
    }
}
Run Code Online (Sandbox Code Playgroud)

所以只要你不向上转型并且不让不安全的东西逃脱,演员就是安全的。