简体   繁体   English

为什么将ArrayList的泛型转换为超类不起作用?

[英]Why does casting an ArrayList 's generic to a superclass not work?

Can someone please explain to me why the line marked //this line gives a compile error (why?) in the following code sample does not work? 有人可以向我解释为什么标记为//this line gives a compile error (why?)在下面的代码示例中不起作用?

import java.util.ArrayList;

public class GenericCastCheck {

    class A{
    }

    class B extends A{
    }

    public static void main(String[] args) {

        A aObject = new A();
        B bObject = new B();

        //this line works fine
        aObject = bObject;
        //this line gives a compile (expected)
        bObject = aObject;

        ArrayList<A> aList = new ArrayList<A>();
        ArrayList<B> bList = new ArrayList<B>();

        //this line gives a compile error (why?)
        aList = bList;
        //this line gives a compile error (expected)
        bList = aList;
    }
}

Specifically, when we say that bList is of type ArrayList<B> , does it not mean that each element of it is an instance of B ? 具体来说,当我们说bList的类型为ArrayList<B> ,是否并不意味着它的每个元素都是B的实例? If so, then what is the problem in casting it to ArrayList<A> , if we can cast individual instances of B to A ? 如果是这样,那么它是什么铸造的问题ArrayList<A> ,如果我们都可以投射单个实例BA

Thanks. 谢谢。

The problem is this: 问题是这样的:

ArrayList<A> aList = new ArrayList<A>();
ArrayList<B> bList = new ArrayList<B>();
aList = bList; // if this were valid...
aList.add(new A()); // ...what should happen here?
B b = bList.get(0); // ...and here?

If you do the same thing with arrays, you get an ArrayStoreException in line 4 at runtime. 如果对数组执行相同的操作,则会在运行时在第4行中获得ArrayStoreException。 For generic collections, it was decided to prevent that kind of thing at compile time. 对于通用集合,决定在编译时阻止这种事情。

Because generic are strict. 因为通用是严格的。 they aren't covarient 他们不是共同的

ArrayList<A> aList can only refer to an ArrayList of type A ArrayList<A> aList只能引用类型AArrayList


From wiki 来自维基

Unlike arrays, generic classes are neither covariant nor contravariant. 与数组不同,泛型类既不是协变的也不是逆变的。 For example, neither List<String> nor List<Object> is a subtype of the other: 例如, List<String>List<Object>都不是另一个的子类型:

 // a is a single-element List of String List<String> a = new ArrayList<String>(); a.add("foo"); // b is a List of Object List<Object> b = a; // This is a compile-time error 

However, generic type parameters can contain wildcards (a shortcut for an extra type parameter that is only used once). 但是,泛型类型参数可以包含通配符(仅使用一次的额外类型参数的快捷方式)。 Example: Given a requirement for a method which operates on Lists, of any object, then the only operations that can be performed on the object are those for which the type relationships can be guaranteed to be safe. 示例:由于需要对任何对象的列表进行操作的方法,因此可以对对象执行的唯一操作是可以保证类型关系安全的操作。

 // a is a single-element List of String List<String> a = new ArrayList<String>(); a.add("foo"); // b is a List of anything List<?> b = a; // retrieve the first element Object c = b.get(0); // This is legal, because we can guarantee // that the return type "?" is a subtype of Object // Add an Integer to bbadd(new Integer (1)); // This is a compile-time error; // we cannot guarantee that Integer is // a subtype of the parameter type "?" 

Wildcards can also be bound, eg " ? extends Foo " or " ? super Foo " for upper and lower bounds, respectively. 通配符也可以绑定,例如分别为上限和下限“ ? extends Foo ”或“ ? super Foo ”。 This allows to refine permitted performance. 这允许改进允许的性能。 Example: given a List<? extends Foo> 示例:给出一个List<? extends Foo> List<? extends Foo> , then an element can be retrieved and safely assigned to a Foo type (covariance). List<? extends Foo> ,然后可以检索元素并将其安全地分配给Foo类型(协方差)。 Given a List<? super Foo> 鉴于List<? super Foo> List<? super Foo> , then a Foo object can be safely added as an element (contravariance). List<? super Foo> ,然后可以安全地添加Foo对象作为元素(逆变)。

Animesh, 的Animesh,

Even though class B is subtype of A, ArrayList< B > is not a subtype of ArrayList < A >. 即使B类是A的子类型,ArrayList <B>也不是ArrayList <A>的子类型。 Its on the same line as in B[] is not subtype of A[]. 它与B []在同一行上不是A []的子类型。 These are two independent unrelated types. 这是两种独立的不相关类型。

Because there is no subtype relation in Java between C<A> and C<B> , even if A is a supertype of B or vice versa. 因为在C<A>C<B>之间Java中没有子类型关系,即使AB的超类型,反之亦然。

If your interested in the details lookup co- / contra-variance in Wikipedia. 如果您对Wikipedia中的详细信息查找co / / contra-variance感兴趣。

Note, that in Java arrays are co-variant, which means A[] is a supertype of B[] if A is a supertype of B . 注意,在Java数组是共变型中,这意味着A[]是的超类型B[]如果A是的超类型B That is the reason why you sometimes get strange cast exception with arrays. 这就是为什么你有时会得到奇怪的数组转换异常的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM