通用方法失败

时间:2009-02-18 03:15:59

标签: java generics

我通过改编书中的一篇文章来编写这个简单的测试代码,以帮助我理解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>时有效,这很好,但我仍然不确定我是否可能错过了某些内容,或者我从中获取的这本书可能有一个失误。请阅读那里出现的问题:

  1. 给定一个声明为:
  2. 的方法
      

    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的错误,或者我在这里遗漏了什么?

3 个答案:

答案 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必须遵守的合同。