2016-10-25 74 views
1

我有以下代码:泛型:为什么在通配符中使用通配符进行转换,而在方法参数传递中允许使用通配符?

public static void swap(List<?> list) { 
    swapHelper(list); //1 
} 

private static <E> void swapHelper(List<E> list) { 
    swap(list); //2 
} 

{ 
    List<?> tW = new ArrayList<>(); 
    List<E> tE = new ArrayList<>(); 

    tW = tE; // 3 
    tE = tW; // 4 
} 

在这行代码1和2编译成功,没有这意味着: 我可以分配的List<?>到的List<E>引用,反之亦然? 如果是这样,那么为什么第4行不编译。

回答

-2

<?><E>都是未知类型;但是所有的List<?> s都有的一些类型的元素,所以您可以调用参数为List<E>的方法,因为存在一些与其匹配的未知类型。

注意,你不能做到这一点:

public static void swap(Object object, List<?> list) { 
    swapHelper(object, list); // Compiler error: object not in bounds of list. 
} 

private static <E> void swapHelper(E object, List<E> list) { 
    swap(object, list); // OK. 
} 

,因为你现在不知道,如果ObjectList<?>的范围内。

你也不能添加新的非空值的列表:

private static <E> void swapHelper(List<E> list) { 
    list.add(new E()); // Can't create an instance of type variable. 
    swap(list); 
} 

,但你可以添加你从列表中取值,因为它们是已知的列表的范围内:

private static <E> void swapHelper(List<E> list) { 
    list.add(list.get(0)); 
    swap(list); 
} 

所以它是类型安全的做调用从swapswapHelper,因为你不能使东西是不强制转换为E(不管这类型)到列表中。

  • 如果分配tW = tE,你不能添加任何其他tWnull,所以你不能把tE的状态下,它含有比实例以外的任何其他:

    tWtE

    同样的E

  • 如果你被允许指定tE = tW,你可以添加E非空实例tE。这可能意味着您可以将错误类的实例添加到tW,这可能会导致运行时类型错误。因此,这项任务是被禁止的。

请记住,分配列表不会导致要复制的列表:如果您分配tE = tW,然后tE == tW,所以适用于所有tE的变化中也可以看到通过tW,因为它们是同一个实例。

+0

downvoter:照顾解释? –