說明:
@SafeVarargs 是jdk1.7引入的適用於可變參數與泛型能夠更好結合的一個注解。
官方解釋:
程序員認定帶有注釋的主體或者構造函數不會對其執行潛在的不安全操作
將此注釋應用於未經檢查的方法或者構造器在"不可具體化"的和未經檢查的參數類型
警告關於所有數組參數創建的時候
除了強加使用@Target 元注解的限制之外,編譯器還被用在注解類型上來實現額外的限制
下面幾種情況會在使用@SafeVarags 注解的時候產生編譯時錯誤:
在聲明一個固定參數的方法或者構造函數的時候
也就是說如果你認為你的方法或者構造方法是類型安全的,那么你也就可以使用@SafeVarargs 來跳過@SuppressWarnings("unchecked")檢查。
示例:
public class SafeVarargs {
// 這其實不是一個安全的類型檢查
@SafeVarargs
static void m(List<String>...lists){
// 先會存儲到 array[0] 的位置
Object[] array = lists;
List<Integer> tmpList = Arrays.asList(42);
// array[0] 又保存了tmpList(Integer)進行覆蓋
// tmpList是一個List對象(類型已經擦除),賦值給Object類型的對象是允許的(向上轉型),
// 能夠編譯通過
array[0] = tmpList;
// 實際取出來的應該是 42
String s = lists[0].get(0);
}
public static void main(String[] args) {
List<String> list1 = Arrays.asList("one","two");
m(list1);
}
}
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at java7.SafeVarargs.m(SafeVarargs.java:14)
at java7.SafeVarargs.main(SafeVarargs.java:21)
Process finished with exit code 1
具體分析:
List<String> list1 = Arrays.asList("one","two");
當程序執行到這一步,會創建一個list1 ,其內部存在兩個固定的值 [one,two],
調用m(list1)方法
m(list1);
接着
Object[] array = lists;
程序執行到這一步,會在array數組中的第0個位置上存儲一個list1 對象
List<Integer> tmpList = Arrays.asList(42);
創建一個Integer的列表,存儲一個integer類型的元素42
array[0] = tmpList;
重新給array[0] 進行賦值,把原來位置的lists 進行覆蓋,存儲新的元素tmpList
String s = lists[0].get(0);
我們預期的結果應該是取的值是42,但是實際上卻報出了ClassCastException
因為最后array[0] 中的值 42Integer 類型, 無法直接用String 對象進行接受,所以會報錯。
參考: http://softlab.sdut.edu.cn/blog/subaochen/2017/04/safevarargs的用法/
http://book.51cto.com/art/201205/339154.htm