我通过改编书中的一篇文章来编写这个简单的测试代码,以帮助我理解Java中泛型方法的工作。我标记的行是假设工作,为什么不呢?
import java.util.*;
class Test {
public static void main(String args[]){
List<Number> input = null;
List<Number> output=null;
output = Test.process(input); // fail, why??
}
public static <E extends Number> List <? super E> process (List <E> nums){
List <E>eList = new ArrayList<E>();
return eList;
}
}
编辑:嗯,代码在将List<? super E>
更改为List<E>
时有效,这很好,但我仍然不确定我是否可能错过了某些内容,或者我从中获取的这本书可能有一个失误。请阅读那里出现的问题:
public static&lt; E extends Number&gt;名单 &LT; ?超级E&gt;过程(列表名称)
程序员想要使用这样的方法:
// INSERT DECLARATIONS HERE
output = process(input);
可以在// INSERT DECLARATIONS这里放置哪些声明对以允许 要编译的代码? (选择所有适用的选项。)
A. ArrayList<Integer> input = null;
ArrayList<Integer> output = null;
B. ArrayList<Integer> input = null;
List<Integer> output = null;
C. ArrayList<Integer> input = null;
List<Number> output = null;
D. List<Number> input = null;
ArrayList<Integer> output = null;
E. List<Number> input = null;
List<Number> output = null;
F. List<Integer> input = null;
List<Integer> output = null;
G. None of the above.
答案:B,E和F是正确的。
返回类型的进程肯定被声明为List
,而不是ArrayList
,所以A和D.
错了。 C是错误的,因为返回类型的计算结果为List<Integer>
,但不能
被分配给List<Number>
类型的变量。当然所有这些都可能导致
NullPointerException
因为变量仍为空 - 但问题只是问我们
获取编译代码。
本书中提到的所有选项都没有对我的代码起作用。我可以安全地将其标记为Kathy Sierra的错误,或者我在这里遗漏了什么?
答案 0 :(得分:7)
问题在于您将方法的返回类型声明为
List<? super E>, i.e. List<? super Number>
但是将其分配给
List<Number>
所以你应该把它分配给
List<? super Number>
或将返回类型声明为
List<E> i.e. List<Number>
(详细格式,因为内联代码不能正确显示泛型。)
如果书中声称可以按照你描述的方式分配方法的返回值,那么这本书似乎确实是错误的。如果方法返回E列表(如上所述)将是正确的。
答案 1 :(得分:1)
尝试:
import java.util.*;
class Test {
public static void main(String args[]){
List<Number> input = null;
List<Number> output=null;
output = Test.process(input); // fail, why??
}
public static <E extends Number> List <E> process (List <E> nums){
List <E>eList = new ArrayList<E>();
return eList;
}
}
答案 2 :(得分:0)
您的方法返回List
。我们不知道它是什么 ,但它绝对是Number
的一些超类的列表。例如:也许它正在返回Object
的列表 - 调用者不知道。但是,我们知道无论它返回什么类型的List
,都可以将Number
放入其中。
您要将其分配给List of Number
。这意味着无论何时拨打output.get(n)
,您都将获得Number
返回。
看到问题? process()
的返回值不符合output
必须遵守的合同。