是什么List<?>
意思,它是否仅仅意味着未指定类型的对象列表?
谷歌搜索该字符串<?>
不会返回任何有用的信息(:
正如汤姆所说,?
或无界通配符意味着未指定对象的类型。它可能是未知的,可能意味着多个可能的值,或者可能只是无关紧要。您的示例 ,List<?>
发音为“未知列表”。它很方便,因为它很灵活,但也有一些陷阱,因为你不能将随机物体推入并将它们从未知群体中拉出来而完全不受惩罚。
资源:
顺便说一句,您的 Google 搜索失败了,因为 Google 没有使用特殊字符:
除了一些例外,标点符号会被忽略(也就是说,您不能搜索@#$%^&*()=+[]\ 和其他特殊字符)。
(编辑:我昨晚写这篇文章时一定很累。清理格式/添加了一些信息。)
您需要获取更多信息的关键字是通配符
要回答这个问题,我需要解释无界通配符和有界通配符。
这篇文章的内容是从 java 文档中组装而成的。
无界通配符类型使用通配符 (
?
) 指定,例如List<?>
。这称为未知类型列表。在两种情况下,无界通配符是一种有用的方法:
如果您正在编写一个可以使用 Object 类中提供的功能实现的方法。
当代码使用泛型类中不依赖于类型参数的方法时。例如,
List.size
或List.clear
。事实上,Class<?>
之所以经常使用,是因为其中的大多数方法Class<T>
都不依赖于T
.
考虑一个可以绘制矩形和圆形等形状的简单绘图应用程序。要在程序中表示这些形状,您可以定义一个类层次结构,如下所示:
public abstract class Shape {
public abstract void draw(Canvas c);
}
public class Circle extends Shape {
private int x, y, radius;
public void draw(Canvas c) {
...
}
}
public class Rectangle extends Shape {
private int x, y, width, height;
public void draw(Canvas c) {
...
}
}
这些类可以在画布上绘制:
public class Canvas {
public void draw(Shape s) {
s.draw(this);
}
}
任何绘图通常都会包含许多形状。假设它们被表示为一个列表,那么在 Canvas 中有一个方法来绘制它们会很方便:
public void drawAll(List<Shape> shapes) {
for (Shape s: shapes) {
s.draw(this);
}
}
现在,类型规则说
drawAll()
只能在完全为 Shape 的列表上调用:例如,它不能在 a 上调用List<Circle>
。这是不幸的,因为该方法所做的只是从列表中读取形状,所以它也可以在List<Circle>
. 我们真正想要的是该方法接受任何形状的列表: public void drawAll(List shapes) { ... } 这里有一个很小但非常重要的区别:我们List<Shape>
用List<? extends Shape>
. 现在drawAll()
将接受 的任何子类的列表Shape
,因此我们现在可以根据需要在 a 上调用它List<Circle>
。
List<? extends Shape>
是有界通配符的一个示例。代表未知类型,但是,在这种?
情况下,我们知道这种未知类型实际上是 Shape 的子类型。(注意:它可以是 Shape 本身,也可以是某个子类;它不需要从字面上扩展 Shape。)我们说 Shape 是通配符的上限。
类似地,作为有界通配符的语法? super T
表示未知类型,它是 T 的超类型。ArrayedHeap280<? super Integer>
例如,A 包括ArrayedHeap280<Integer>
、ArrayedHeap280<Number>
和ArrayedHeap280<Object>
。正如您在Integer 类的 java 文档中看到的那样,Integer 是 Number 的子类,而 Number 又是 Object 的子类。
List
: 完全没有类型限制和赋值限制。List<Object>
: 好像和 一样使用List
,但是在接受其他泛型赋值时会出现编译错误。List<?>
: 是泛型。在赋值之前,它意味着它可以接受任何类型的集合赋值,但是在赋值之后,你不能add
元素到它,但是你可以remove
and clear
,而不是immutable set
. List<?>
一般用作接收外部集合的参数,或返回特定元素类型的集合,也称为wildcard collection
.测试代码和结果如下:
List a1 = new ArrayList();
a1.add(new Object());
a1.add(new Integer(10));
a1.add(new String("string"));
System.out.println("List is : " + a1);
List<?> a4 = a1;
a4.remove(0);
System.out.println("List is : " + a4);
System.out.println("List is : " + a4.get(0));
a4.clear();
System.out.println("List is : " + a4);
结果是:
List is : [java.lang.Object@2a139a55, 10, string]
List is : [10, string]
List is : 10
List is : []
听起来您应该查找一些有关 Java 泛型的文档。
这List<?>
意味着它是一个基于当前未指定类型的对象。该规范是在实例化类时制定的。
例如:
List<String> listOfStrings = new ArrayList<String>();
是字符串对象的列表。
List
是一个您可以自己实现的接口,也可以由一些 Java 集合实现,例如Vector
.
您可以使用尖括号提供编译时键入信息。最通用的类型Object
是List<Object>
. 您看到的<?>
是表示某个子类的 ListObject
或Object
. 这就像说List<? extends Object>
, or List<? extends Foo>
,其中List
包含某个子类的Foo
对象或Foo
自身的对象。
你不能实例化一个List
; 它是一个接口,而不是一个实现。
List<?>
代表List<? extends Object>
所以Collection<E>
你会发现containsAll(Collection<?> c)
它允许你写
List<Object> objs = Arrays.<Object>asList("one",2,3.14,4);
List<Integer> ints = Arrays.asList(2,4);
assert objs.containsAll(ints);//true
当您从集合中取出一个元素时,您必须将其转换为存储在集合中的元素类型。除了不方便之外,这也是不安全的。编译器不会检查您的转换是否与集合的类型相同,因此转换可能会在运行时失败。
泛型为您提供了一种将集合类型传达给编译器的方法,以便对其进行检查。一旦编译器知道集合的元素类型,编译器就可以检查您是否始终如一地使用该集合,并且可以对从集合中取出的值插入正确的强制转换。
? 只是泛型中的通配符
泛型中有 3 种不同类型的通配符
1)上界通配符:使用extends关键字
eg: List<? extends SuperClass>
2) 下界通配符
eg:Uses Super key word List<? super SubClass>
3) 无界通配符
List<?> list
您可能正在查看基于模板的List
类。List<String> myList = new MyList<String>();
作为示例,您可以创建一个字符串列表。检查它支持的所有类型的文档。它应该支持任何对象类型,但如果有排序功能,您必须提供一些比较功能。
请注意,在上面的示例中,是一个在 JavaMyList
中实现接口的具体类。List
可以ArrayList
。
编辑:我List
错误地认为是一个具体的类。修复了上面的错误。谢谢乔恩。