在继承的情况下,ArrayList和Arrays.asList对于Collection的工作方式有所不同

时间:2018-06-27 09:43:01

标签: java generics inheritance collections

int value = 0;
for (int i = 0; i < array.length; i++) {
    if (array[i].isSelected()) {
        value |= (1 << i);
    }
}

3 个答案:

答案 0 :(得分:3)

它们的行为没有不同,您使用它们的方式也不同。

在此,您要让编译器确定由List返回的Arrays.asList的类型,并且在给定List<A>所需参数的情况下,编译器将其确定为checkWithoutInheritance()。 :

s.checkWithoutInheritance(Arrays.asList(new B()));

这里您将List<B>传递给方法,因此编译器别无选择,只能失败:

List<B> list = new ArrayList<>();
s.checkWithoutInheritance(list);

如果您同时使用两个List,则会得到相同的输出:

均失败:

List<B> list = new ArrayList<>();
List<B> list2 = Arrays.asList(new B());
s.checkWithoutInheritance(list2); 
s.checkWithoutInheritance(list);

两个都可以工作

s.checkWithoutInheritance(Arrays.asList(new B()));
s.checkWithoutInheritance(new ArrayList<>());

对于checkWithInheritance(final Collection<? extends A> s),它同时接受List<A>List<B>,这就是为什么您的checkWithInheritance调用都通过编译的原因。

答案 1 :(得分:1)

有方法时:

void checkWithoutInheritance(final Collection<A> s);

该行:

s.checkWithoutInheritance(Arrays.asList(new B()));

工作正常,因为它与:

相同
List<A> list = Arrays.asList(new B());
s.checkWithoutInheritance(list);

但是,以下代码:

List<B> list = new ArrayList<B>();
s.checkWithoutInheritance(list); // compiler error

产生编译器错误,因为无法将泛型are not covariantList<B>分配给List<A>

List<B> listb = new ArrayList<B>();
List<A> lista = listb; // Incompatible types error, even though B extends A

有方法时:

void checkWithInheritance(final Collection<? extends A> s);

<? extends A> wildcard放宽了对变量s的限制,因此两者均有效:

s.checkWithInheritance(new ArrayList<A>());
s.checkWithInheritance(new ArrayList<B>());

<? extends A>适用于AA子类型的列表。

答案 2 :(得分:0)

List<B> list;

这将声明一个变量,它是一个列表,并保证该列表中的所有内容都可以强制转换为B(即BB的子类或{ {1}} B`。

null), to which you can only add things which can be cast to

这声明了一个方法,接受一个参数,该参数是一个集合,并保证该集合中的所有内容都可以强制转换为private void checkWithoutInheritance(final Collection<A> s) { ,您只能向其中添加可以强制转换为{{1} }。

这意味着A可以做到这一点:

A

如果您能够拨打电话

checkWithoutInheritance

然后,s.add(new A()); 现在将包含checkWithoutInheritance(list); 的实例,该实例不能转换为list,从而违反了A内容的保证。

因此,编译器不允许这样做。编译器不在乎您不要B添加list,因为您可以。出于安全考虑,这是错误的。


另一方面:

A

这声明了一个方法,接受一个参数,该参数是一个集合,并保证该集合中的所有内容都可以转换为 s 的某些子类。

您无法向其中添加private void checkWithInheritance(final Collection<? extends A> s) { ,因为您不知道“某个子类”是指AA还是其他完全含义。

因此,您无法在其方法主体中写入A,因此将B传递给它是安全的。