Java:当B实现A时,从List <B>转换为List <A>?

Mat*_*ins 4 java generics inheritance casting list

我定义了以下类和接口:

public interface A {
}

public class B implements A {
}
Run Code Online (Sandbox Code Playgroud)

我有一个ListB,我需要转换为对象ListA对象:

List<B> listB = new List<B>();
listB.add(new B());  // dummy data
listB.add(new B());  // dummy data
listB.add(new B()); // dummy data

List<A> listA = (List<A>) listB;
Run Code Online (Sandbox Code Playgroud)

上面的最后一行导致编译错误"无法从列表<B>转换为列表<A>".我尝试用以下方法解决这个问题:

List<A> listA = Arrays.asList((A[]) listB.toArray());
Run Code Online (Sandbox Code Playgroud)

不幸的是,这会抛出一个ClassCastException.有谁知道我怎么解决这个问题?

Bal*_*usC 14

你不能这样投.创建一个新的:

List<A> listA = new ArrayList<A>(listB);
Run Code Online (Sandbox Code Playgroud)

构造函数需要Collection<? extends A>.无论如何它将指向相同的参考.


new*_*cct 9

您应该学会正确使用它,而不是与语言功能作斗争.

而不是询问如何使用不安全的演员来解决错误,首先要理解为什么会出现错误是有益的; 为什么你要求做的是不安全的(因为你可以使用添加A到列表中listA,然后将其从列表中取出作为B使用listB).

然后,您应该解释为什么您认为您的用例不会遇到不安全的情况.因为对此的回答将提示如何更改代码以使其与泛型一起正常工作.

  • 如果你说这是不是不安全的,因为你永远不添加任何东西使用listA,那么你应该改变的类型listAList<? extends A>.这样,您可以listB直接分配给它而不需要任何强制转换,并且您将无法使用listA(除外null)向其添加任何内容.
  • 如果你说它不是不安全因为你从来没有得到任何东西listB,那么为什么不首先改变listBto 的类型List<A>


Pet*_*rey 6

如果您知道操作是安全的,您可以使用类型擦除.这会产生一个警告,你可以使用@SuppressWarnings关闭它

List<A> listA = (List) listB;
Run Code Online (Sandbox Code Playgroud)

编译器在使用普通强制转换时遇到困难的原因是你现在可以添加一个同样实现A的C类.除非你的原始列表已被更改,现在包含一个C,即使你已经指定它不应该.