1.可變參數的作用在於讓客戶端能夠將可變數量的參數傳給方法,但這是個技術露底:當調用一個可變參數方法時,會創建一個對象數組Object[]用來存放可變參數;這個數組應該是一個實現細節,他是可見的。因此,當可變參數有泛型或者參數化類型時,編譯警告信息就會產混亂。
2.當一個參數化類型的變量指向一個不是該類型的對象時,會產生堆污染(heap pullution)。它導致編輯器的自動生成轉換失敗,破壞了泛型系統的基本保證。
3.java7中,增加了@SafeVarargs註解,它讓帶泛型vararg參數的方法的設計者能夠自動禁止客戶端的警告。本質上@SafeVarargs註解是通過方法的設計者做出承諾,聲明這類型是安全的。所以不要隨意使用@SafeVarargs對方法進行註解,除非它是真正安全的。
代碼示例:
package effectivejava;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
* 謹慎並用泛型可變參數:
* 1.可變參數的作用在於讓客戶端能夠將可變數量的參數傳給方法,但這是個技術露底:當調用一個可變參數方法時,會創建一個對象數組Object[]用來存放可變參數;這個數組應該是一個實現細節,他是可見的。因此,當可變參數有泛型或者參數化類型時,編譯警告信息就會產混亂。2.當一個參數化類型的變量指向一個不是該類型的對象時,會產生堆污染(heap pullution)。它導致編輯器的自動生成轉換失敗,破壞了泛型系統的基本保證。
3.java7中,增加了@SafeVarargs註解,它讓帶泛型vararg參數的方法的設計者能夠自動禁止客戶端的警告。本質上@SafeVarargs註解是通過方法的設計者做出承諾,聲明這類型是安全的。所以不要隨意使用@SafeVarargs對方法進行註解,除非它是真正安全的。
*
* @author wangcaiyan[[email protected]]
*
*/
public class VarargT {
public static void main(String[] args) {
// java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
//允許另一個方法訪問一個泛型可變參數數組是不安全的。
// String[] arr = pickTwo("Good", "Fast", "Cheap");
List<String> strList = new ArrayList<>();
strList.add("work");
dangerous(strList);
}
//unsafe
//當調用一個可變參數方法時,會創建一個對象數組Object[]用來存放可變參數
static <T> T[] toArray(T... args) {
return args;
}
static <T> T[] pickTwo(T a , T b, T c) {
switch (ThreadLocalRandom.current().nextInt(3)) {
case 0:
return toArray(a, b);
case 1:
return toArray(a, c);
case 2:
return toArray(c, b);
}
throw new AssertionError();
}
//當調用一個可變參數方法時,會創建一個對象數組Object[]用來存放可變參數
static void dangerous(List<String>... stringLists) {
List<Integer> intList = new ArrayList<>();
intList.add(42);
Object[] objects = stringLists;
objects[0] = intList; // heap pullution:將List<Integer>放入List<String>
String s = stringLists[0].get(0); // classCastException:java.lang.Integer cannot be cast to java.lang.String
System.out.println(s);
}
}