我很难理解仿制外卡的概念。
根据我的理解<?>
类型未知用于解决泛型中不支持的协方差,它应该适合任何类型的集合,<?extends T>
表示您可以拥有类型集合{{ 1}}或扩展T
的类意味着您可以拥有T.<?super T>
类型的集合T
或超级T
。
如果上述错误,请纠正我。
当我尝试这样写时:
import java.util.*;
public class Gclass {
static Gclass t;
public void write(List< ?super String > lw){
lw.add("b");
}
public void read(List< ? extends String> lr){
String s=lr.get(2);
System.out.println(s);
}
public static void main(String[] args) {
t=new Gclass();
List<String> l=new ArrayList<String>();
l.add("a");
l.add("");
System.out.println(l);
t.write(l);
System.out.println(l);
t.read(l);
System.out.println(l);
}
}
它有效,但我怀疑的地方是:
根据我的理解,(extends和super)都包含声明的类型,因此在这种特殊情况下,我的List
类型为String
。我可以交换extends和super,但是我得到了编译错误?
如果写? super Object
不起作用?它应该工作,因为它是String
的超级
我没有检查读数,因为String
无法扩展,但我想我在这里也错过了一个概念。
我已经阅读了与此问题相关的所有问题的答案,但我仍然无法对此有充分的了解。
答案 0 :(得分:5)
String确实是一个不好的例子,因为它是一个final
类,但请考虑使用Number
之类的东西。
如果某个方法采用List<? extends Number>
类型的参数,那么您可以将其传递给List<Number>
或List<Integer>
或List<BigDecimal>
等。因此,在方法正文中,它是很好地接受列表的 out (因为你知道它们必须是Number
的实例)但是你不能把放在中,因为你没有知道它是否安全(例如,编译器不能让你冒Integer
放入List<Float>
的风险。
相反,如果该方法需要List<? super Number>
,那么您可以传递List<Number>
或List<Object>
- 您无法从此列表中取出任何内容,因为您不知道它的类型是 * ,但你知道将Number
放在中肯定是安全的。
*从技术上讲,你可以解决问题,但你可以指定的唯一类型是Object
答案 1 :(得分:2)
根据我的理解,(
extends
和super
)包含声明的类型(此处为String
),因此在此特定情况下,List
类型为{ {1}} ...我可以交换String
和extends
但我收到编译错误?
你是对的,super
和? extends String
都包含? super String
。但是你错过了String
还包括? super String
,CharSequence
的观点,它不在Object
的范围内。您可以向? extends String
添加String
,无论该列表的类型是什么,它都可以引用List<? super String>
。但是,您无法向String
添加Integer
,因为该列表实际上可能是List<? extends Number>
。
如果写
List<Float>
不起作用?它应该工作,因为它是? super Object
的超级?
String
是Object
的超类适合您String
的位置,并使用? super String
。因此,Object
可以捕获? super String
,但Object
无法捕获? super Object
,因为String
不是String
的超级类型。可以这样想:“实际类型取代Object
,它必须满足?
附带的规则。
答案 2 :(得分:1)
List<? super String>
表示lw
的值为List
且类型参数为String
或超类,因此您可以添加String
值{ {1}}(因为它可以转换为list的类型参数)。
"b"
表示List<? extends String>
的值为lw
,其类型参数为List
或它的子类,因此来自String
的值可以转换为lw
。