2016-10-25 69 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:照顧解釋? –