2.考虑众所周知的代码:
List<? extends String> strs= new ArrayList<String>();
? extends String str;//error
strs.add("sd");//error
为什么? extends String str;
无效?我认为如果我们声明对泛型类型的引用,例如某些类型List<E> strs;
的{{1}},则编译器将类型参数定义为特定类型E
。
我不明白案例E
中发生了什么? List<? extends String> strs
和List<? extends String>
是否在编译时进行类似解析,或List<String>
解析与List<? extends String>
不同的某些可复制类型List<E>
?
答案 0 :(得分:1)
泛型用于指定类型。
考虑以下类def:
public interface List<E> extends Collection<E>
这告诉我们,我们有一个可以容纳任何类型元素的List
请注意E
没有限制。
如果我们定义一个这样的类:
public class MyList<T extends String> implements List<T>
我们现在有一个实现List的MyList,但只接受String
s(或decedents)。
在这个课程中,我们可以参考T
。
public class MyList<T extends String> implements List<T> {
private ArrayList<T> internalStorage;
关键点
在类定义中,我们定义了T
是什么;它是基于String的任何类
因此可以引用类T内部
然而,在实际实例化类之前,T的味道不会得到修复:
MyList<MyStringType> test = new MyList<MyStringType>(parameters); //java 6
MyList<MyStringType> test = new MyList<>(parameters); //java 7, same but shorter.
现在,Java知道T
类中的MyList
意味着什么是T是MyStringType。
支持知识Java编译类并使用对实际类T
的引用替换对MyStringType
的所有引用。
它完全忘记了T。
现在在课堂内注意到,提到的T
到处都会被MyStringType取代
但是如果我想处理一个字符串,但不一定是MyStringType。
解决方案:
我定义了一个像这样的成员:
List<? extends String> strs; //Will fill the data in later
现在我们有一个名为strs的List,它只接受字符串,但不会强制使用MyStringType类型的字符串。
此列表不受T
实例化时修复的MyList
定义的约束
当我们为strs
赋值时,如果修复了List的风格。在您的示例中,它将是一个String列表。
? extends String str;//error
变量无法修复,因为当创建保存变量的类时,无法确定其类型。
答案 1 :(得分:0)
泛型专为读取而非写入而设计。这就是为什么你可以在方法的参数中使用泛型,但是不能用它来声明一个你可以用来读/写的变量: - )