我有一个构建器类,其方法采用未知类型的列表
public class A{
private List<D<?>> data;
public void setData(List<D<?>> data){
this.data=data;
}
}
public class D<T>{
private List<T> data;
public void setData(List<T> data){
this.data=data;
}
}
然后在我的来电课上我有:
public class B{
private A a;
public void apply(A a, List<D<String>> list){
a.setData(list); //It shows an error
}
}
显示以下错误:
List<String>
无法转换为List<?>
我对未知类型的理解是它应该允许这样的基本内容。它们都是java.util.List
有人可以解释为什么会出现这种情况以及解决方法是什么?
答案 0 :(得分:2)
<强>解释强>
如果有,
public void apply(A a, List<D<String>> list){
a.setData(list); //It shows an error
}
它总是限制D
实例的类型在String
的上下文中应始终为apply()
。因为我们在类a
的{{1}}实例中实际拥有的内容可能是A
。编译器会看到此冲突并且不允许编译。
<强>修正:强>
List<D<Integer>>
因为您可以在班级public void apply(A a, List<D<?>> list){
a.setData(list);
}
中为T
添加任何类型。 无界类型参数。
因此,您可以实例化D
个实例,如下所示:
D
根据D<Integer> intD = new D<Integer>();
D<String> stringD = new D<String>();
的类声明(由于Unbounded类型参数),所有这些都是完全可以接受的。
如果我们采用D
个实例,则其stringD
为List
。
与String
实例相同,它的intD
为List
。
答案 1 :(得分:1)
正确输入解决方法:
class A{
private List<? extends D<?>> data;
public void setData(List<? extends D<?>> data){
this.data=data;
}
}
或
class A<T> {
private List<D<T>> data;
public void setData(List<D<T>> data){
this.data=data;
}
}
class B{
private A<String> a;
public void apply(A<String> a, List<D<String>> list){
a.setData(list);
}
}
答案 2 :(得分:0)
public void apply(A a, List<D<String>> list){
a.setData(list); // List<D<String>> cannot be converted to List<D<?>>
}
如果您被允许转换/转换List<D<String>>
到List<D<?>>
,那么您可以在列表中添加D<Integer>
,因为它允许包含任何D
类型,但任何引用该列表的代码都会有一个包含D<Integer>
的列表,只有D<String>
时才会显示。
如上所述,你不能直接投射到List<D<?>>
,但你可以使用(我称之为)“魔法双重投射”;首先到List<?>
然后到List<D<?>>
:
a.setData((List<D<?>>)(List<?>)list); // compiles OK!
当然这是一个不安全的演员,所以你应该确保这样做不会引起问题。