考虑以下代码:
public <T> List<T> meth(List<?> type)
{
System.out.println(type); // 1
return new ArrayList<String>(); // 2
}
它不在第2行编译,说List是必需的。
现在,如果它改为:
public <T> List<?> meth(List<T> type)
{
System.out.println(type); // 1
return new ArrayList<String>(); // 2
}
它确实编译。为什么?我认为使用通配符声明泛型类型和使用通配符之间的区别在于,当使用通配符时,无法向集合中添加新元素。为什么<?>
允许返回List的子类型?我在这里遗漏了一些东西,明确规则是什么以及它是如何应用的?
答案 0 :(得分:4)
区别在于返回类型声明。 List<String>
不是List<T>
的子类型,但它是List<?>
的子类型。
List<?>
不对其类型变量做出任何假设,因此以下语句有效:
List<?> l0 = new ArrayList<String>();
List<?> l1 = new ArrayList<Object>();
List<? extends Number> ltemp = null;
List<?> l2 = ltemp;
List<T>
假设当您将其声明为List<String>
或List<Object>
时,将在客户端(例如,类型使用)的上下文中解析type参数。在方法体内,你也不能对它做任何假设。
答案 1 :(得分:1)
在第一种情况下,T
不一定是String
的超类。如果您选择T
之类的Integer
并调用该方法,则会失败;所以它不会编译。但是,第二个肯定会编译,任何ArrayList<String>
都是某事的有效List
。
答案 2 :(得分:1)
如前所述,String不是T的子类型,因此它不起作用。但是,此代码有效:
public <T> List<T> meth(List<?> type)
{
System.out.println(type); // 1
return new ArrayList<T>(); // 2
}
我认为,更多的是想要你想要的东西。