Java中未绑定通配符泛型的用途和意义是什么?
我不明白非绑定通配符泛型有什么用。当您的方法并不真正关心实际类型时,具有上限Java中未绑定通配符泛型的用途和意义是什么?,java,generics,wildcard,Java,Generics,Wildcard,我不明白非绑定通配符泛型有什么用。当您的方法并不真正关心实际类型时,具有上限未绑定类型的绑定通配符泛型非常有用 一个简单的例子是: public void printStuff(Iterable<?> stuff) { for (Object item : stuff) { System.out.println(item); } } 如果不使用类型参数(即使用原始类型),则可以向集合中添加任何内容: Collection c = new ArrayList<S
未绑定类型的绑定通配符泛型非常有用
一个简单的例子是:
public void printStuff(Iterable<?> stuff) {
for (Object item : stuff) {
System.out.println(item);
}
}
如果不使用类型参数(即使用原始类型),则可以向集合中添加任何内容:
Collection c = new ArrayList<String>();
c.add("foo");
c.add(new Integer(300));
c.add(new Object());
Collection c=newarraylist();
c、 添加(“foo”);
c、 加(新整数(300));
c、 添加(新对象());
请注意,编译器会警告您不要使用原始类型,特别是出于这个原因:它会删除与泛型相关的任何类型检查。当您的方法并不真正关心实际类型时,未绑定类型可能会很有用
一个简单的例子是:
public void printStuff(Iterable<?> stuff) {
for (Object item : stuff) {
System.out.println(item);
}
}
如果不使用类型参数(即使用原始类型),则可以向集合中添加任何内容:
Collection c = new ArrayList<String>();
c.add("foo");
c.add(new Integer(300));
c.add(new Object());
Collection c=newarraylist();
c、 添加(“foo”);
c、 加(新整数(300));
c、 添加(新对象());
请注意,编译器会警告您不要使用原始类型,特别是出于这个原因:它会删除任何与泛型相关的类型检查。而使用原始类型意味着您不了解泛型(因为您很懒,或者代码是很久以前编写的),使用
意味着您了解泛型,并明确强调您的代码可以处理任何类型的对象。而使用原始类型意味着您不了解泛型(因为您懒惰或代码是很久以前编写的),使用
意味着您了解泛型,并明确强调您的代码可以处理任何类型的对象。使用无界通配符只有在包装不使用泛型的旧代码时才有意义,基本上是集合
如果你看看你能用这样一个通用的工具做些什么,它基本上什么都不是。
如果你有一个集合,你不能添加任何东西,如果你试图读出一些东西,你总会得到一个对象
,依此类推
这反过来有助于确保以类型安全的方式处理数据,而使用原始类型会导致编译器忽略您所造成的任何混乱
from可能会引起兴趣。在包装不使用泛型的旧代码(基本上是集合)时,使用无界通配符才有意义
如果你看看你能用这样一个通用的工具做些什么,它基本上什么都不是。
如果你有一个集合,你不能添加任何东西,如果你试图读出一些东西,你总会得到一个对象
,依此类推
这反过来有助于确保以类型安全的方式处理数据,而使用原始类型会导致编译器忽略您所造成的任何混乱
当您需要执行instanceof
检查时,可能会感兴趣。
不能像这样参数化:
Object value;
if (value instanceof List<String>) {
// ...
}
对象值;
if(列表的值实例){
// ...
}
所以你会:
Object value;
if (value instanceof List<?>) {
// ...
}
对象值;
if(列表的值实例){
// ...
}
当您需要执行instanceof
检查时
不能像这样参数化:
Object value;
if (value instanceof List<String>) {
// ...
}
对象值;
if(列表的值实例){
// ...
}
所以你会:
Object value;
if (value instanceof List<?>) {
// ...
}
对象值;
if(列表的值实例){
// ...
}
对于未绑定通配符,存在(很少)完全正确的用例。SDK包含其中的一些
一个例子是一个方法,它对任何类型的列表执行确定操作,并且在集合中不返回任何作为旋转的:
static void rotate(List<?> list, int distance)
静态空心旋转(列表,整数距离)
另一个示例是,当您想列出类的可能构造函数时,方法是:
Constructor<?>[] getConstructors()
Constructor[]getConstructors()
这里甚至不可能使用泛型,因为根据定义,数组将包含不同的构造函数,每个构造函数都有自己的实际类。相比之下,API使用通用签名来获取单个构造函数:constructor getConstructor(Class…parameterTypes)
结论是,即使它主要用于与旧代码的兼容性,仍然有一些地方未绑定的通配符泛型是正确的方法。有(很少)完全正确的未绑定通配符用例。SDK包含其中的一些
一个例子是一个方法,它对任何类型的列表执行确定操作,并且在集合中不返回任何作为旋转的:
static void rotate(List<?> list, int distance)
静态空心旋转(列表,整数距离)
另一个示例是,当您想列出类的可能构造函数时,方法是:
Constructor<?>[] getConstructors()
Constructor[]getConstructors()
这里甚至不可能使用泛型,因为根据定义,数组将包含不同的构造函数,每个构造函数都有自己的实际类。相比之下,API使用通用签名来获取单个构造函数:constructor getConstructor(Class…parameterTypes)
结论是,即使它主要用于与旧代码的兼容性,仍然有一些地方使用未绑定的通配符泛型是正确的方法。请允许我重新表述这个问题:
“列表
和列表
之间有什么区别?”
答案是列表
更具限制性。它告诉我们,我们有一堆某种类型的对象,但这种类型不一定是对象
因为我们不知道该类型是什么,所以根本无法添加到列表中-我们添加的任何内容都可能是错误的类型。事实上,我们不能将任何?
类型的参数传递给任何方法,而不仅仅是add()
另一方面,当我们指定一个方法采用List
时,它可以采用List
或List
或任何其他List
<代码>列表
只能获取列表