2009-02-18 42 views
1

我编写了这个简单的测试代码,通过调整一本书的内容来帮助我理解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>时的作品,这是伟大的,但我仍然不知道我可能已经错过了一些东西,或者如果我把这个从书中可能有错误。因为它似乎有请阅读问题:

  • 鉴于声明的方法:
  • 公共静态<é扩展号码>列表 <?超级E>进程(名单NUMS)

    程序员想要使用此方法是这样的:

    // 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的错误,还是我在这里错过了一些东西?

    回答

    7

    的问题是,你声明你的方法的返回类型为

    List<? super E>, i.e. List<? super Number> 
    

    但它所以,你要么分配到

    List<Number> 
    

    将其分配给

    List<? super Number> 
    

    或声明的返回类型为

    List<E> i.e. List<Number> 
    

    (详细格式,因为内联代码没有正确显示泛型。)

    如果图书权利要求分配方法的返回值的方式是可能你描述它然后确实在书中似乎是一个错误。如果该方法返回了E列表(如上所述),那将是正确的。

    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; 
        } 
    
    } 
    
    +0

    也许你的代码示例的简短解释? :) – 2009-02-18 03:24:00

    +0

    噢.. 你为什么拿走名单? – andandandand 2009-02-18 03:25:43

    0

    您的方法返回List。我们不知道它是什么,但它绝对是一些超类Number的列表。例如:也许它返回了一个Object的列表 - 调用者不知道。但是,我们知道无论它是否返回List,都可以将Number加入其中。

    您正在将其分配给List of Number。这意味着只要你拨打output.get(n),你总是会收到Number

    看到问题了吗? process()的返回值不符合output必须遵守的合同。