关于java:Generic Method Fail

Generic Method Fail

我编写了这个简单的测试代码,通过修改一个书中的一个片段来帮助我理解Java中泛型方法的工作。我标的那条线应该管用,为什么不行?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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改成List的时候,代码是有效的,这很好,但是我仍然不确定我是否遗漏了什么,或者我从这本书中得到的可能有错误。请仔细阅读问题:

  • 给定的方法声明为:
  • public static < E extends Number > List
    < ? super E > process (List nums)

    程序员希望使用如下方法:

    1
    2
    // INSERT DECLARATIONS HERE
        output = process(input);

    哪些声明对可以放在//此处插入声明以允许要编译的代码?(选择所有适用项。)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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,而它不能分配给List类型的变量。当然,所有这些可能会导致NullPointerException,因为变量仍然为空,但问题只问我们获取要编译的代码。

    书中提到的所有选项都没有对我的代码起作用。我能安全地在凯西·塞拉的身上把它标记为一个错误吗?还是我在这里遗漏了什么?


    问题是,您要将方法的返回类型声明为

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

    但分配给

    1
    List<Number>

    所以你应该把它分配给

    1
    List<? super Number>

    或将返回类型声明为

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

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

    如果书中声称按照您描述的方式分配方法的返回值是可能的,那么实际上,在书中它似乎是一个错误。如果方法返回一个e列表(如上所述),则是正确的。


    尝试:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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;
        }

    }


    方法返回一个List。我们不知道它是什么列表,但它绝对是一个Number的超类列表。例如:也许它返回了一个Object的列表-调用方不知道。然而,我们知道,不管它返回的是哪种类型的List,把Number放进去总是可以的。

    您将它分配给一个List of Number。这意味着,无论何时你打电话给output.get(n),你总会得到一个Number

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