泛型:下界通配符与上限通配符



我理解PECS(生产者扩展,消费者超级(的概念,但仍然对这些符号感到困惑:

public class PECSTest {
public static void main(String[] args) {
//List<? extends Object> ProducerList = new ArrayList<String>();
//ProducerList.add("1"); // Line 1 :compileTimeError
PECSTest myTest = new PECSTest();
List<String> myList = new ArrayList<String>();
myList.add("abc");
myTest.printMyList(myList);
}
private void printMyList(List<? extends Object> myList) {
// TODO Auto-generated method stub
int i=0;
while(i<myList.size()) {
System.out.println(myList.get(i).getClass()); //Line 2
System.out.println(myList.get(i).charAt(0)); // Line 3
System.out.println(myList.get(i).equals(new String("abc")));
i++;
}
}
}
  • 即使我创建了一个可以接受任何扩展 Object 类的对象的列表,但是当我尝试添加字符串时,它在第 1 行给出了编译时错误。为什么会这样?
  • 在第二种情况下,当我将我的 List 传递给 printMyList 方法时,它会在第 2 行以字符串形式打印每个元素类类型,但在第 3 行,为什么我无法调用任何特定于字符串类的方法,如charAt。还有为什么字符串不需要强制转换。

同样在消费者的情况下

List<? super Number> myList = new ArrayList<Object>();
myList.add(new Object());// compile time error

为什么我不能在 myList 中添加对象。因为如果我们使用 super,这意味着这个列表可以包含等于且高于 Java 类层次结构中数字的对象。因此,新的 Object(( 应该按照该语句添加到列表中。

谢谢。

List已经是一个泛型,所以你不应该将其类型设置为泛型;如果你想让它接受所有类型,所以把它的类型设置为Object;另外,你不应该在实例化中指定类型,因为 Java 可以从类型声明中推断它:

List<Object> ProducerList = new ArrayList<>();

多亏了Java多态性,ProducerList现在允许所有类型的,因为所有类都是Object类的专用化。

由于printMyList的参数myList接受不止一种类型,因此您必须在强制转换之前检查其传递的类型以调用其方法,例如StringcharAt()

if (myList.get(i) instanceof String) { 
System.out.println(((String)myList.get(i)).charAt(0)); // Line 3
}

完整的工作代码:

import java.util.*;
class PECSTest
{
public static void main(String[] args) {
List<Object> ProducerList = new ArrayList<>();
ProducerList.add("1"); // Line 1
PECSTest myTest = new PECSTest();
List<String> myList = new ArrayList<String>();
myList.add("abc");
myTest.printMyList(myList);
}
private void printMyList(List<? extends Object> myList) {
int i=0;
while(i<myList.size()) {
System.out.println(myList.get(i).getClass()); //Line 2
if (myList.get(i) instanceof String) { 
System.out.println(((String)myList.get(i)).charAt(0)); // Line 3
}
System.out.println(myList.get(i).equals(new String("abc")));
i++;
}
}
}

输出:

class java.lang.String
a
true

旁注:为什么要在Number(List<? super Number>(上使用下界通配符?可能List<? extends Number>允许Number的每个子类而不是每个不是NumberObject......

最新更新