我有以下课程&接口定义:
public interface A {
}
public class B implements A {
}
我有List
B
个List
个对象需要投放到A
个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;
个对象:
List<A> listA = Arrays.asList((A[]) listB.toArray());
上面的最后一行导致编译错误“无法从列表&lt; B&gt;转换为List&lt; A&gt;”。我尝试用以下方法解决这个问题:
ClassCastException
不幸的是,这会引发{{1}}。有谁知道我怎么解决这个问题?
答案 0 :(得分:14)
你不能这样投。创建一个新的:
List<A> listA = new ArrayList<A>(listB);
构造函数需要Collection<? extends A>
。无论如何它都会指向相同的参考文献。
答案 1 :(得分:9)
您应该学会正确使用它,而不是与语言功能作斗争。
不是询问如何使用不安全的强制转换来解决错误,而是先了解为什么出现错误,这是有益的。 为什么您要求做的事情是不安全的(因为您可以使用A
将listA
添加到列表中,然后将其作为{{1}从列表中删除使用B
)。
然后,您应该解释为什么您认为您的用例不会遇到不安全的情况。因为对此的回答将提示如何更改代码以使其与泛型一起正常工作。
listB
添加任何内容,那么您应该将listA
的类型更改为listA
。这样,您可以直接为List<? extends A>
分配listB
而无需任何演员表,并且您将无法使用listA
向其添加任何内容(null
除外)。listB
获取任何内容,那么为什么不首先将listB
的类型更改为List<A>
?答案 2 :(得分:6)
如果您知道操作是安全的,您可以使用类型擦除。这会产生一个警告,你可以使用@SuppressWarnings
关闭它List<A> listA = (List) listB;
编译器在使用普通强制转换时遇到困难的原因是你现在可以添加一个同样实现A的C类。除非你的原始列表已被更改,现在包含一个C,即使你已经指定它不应该。
答案 3 :(得分:3)
List<A> listA = (List<A>)(List<?>) listB;
不推荐。
答案 4 :(得分:1)
我确定你需要制作整个清单列表&lt; A&gt;(在那里进行奇怪的解析)以及添加新B对象时用(A)
投射它们listA.add( (A) new B()); // dummy data
答案 5 :(得分:0)
这只是一个宣言问题。不要将listB声明为List但作为List或List。
List<A> 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 = listB;
就这么简单。 如果你想强制listB为List(避免添加任何非B元素),你将被迫使用:
List<A> listA = new ArrayList<A>(listB);
但正如他们已经指出的那样,如果你被迫这样做,这不是一个好兆头。
答案 6 :(得分:0)
我们可以使用Generics和Wildcards实现这一目标。您可能无法创建List<A>
,但创建了类似List<? extends A>
的内容,它将调用界面的所有方法,这对我认为最多。
创建新集合非常昂贵且不可取。由于相同对象的引用将被传递到新集合中,因此额外的列表创建步骤只是一个开销。
List<B> bList = new ArrayList<B>();
List<? extends A> aList = bList;