日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java泛型程序设计——Varargs 警告+不能实例化类型变量

發布時間:2023/12/3 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java泛型程序设计——Varargs 警告+不能实例化类型变量 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【0】README

0.1) 本文描述+源代碼均 轉自 core java volume 1, 旨在理解 java泛型程序設計 的 Varargs 警告+不能實例化類型變量 的知識;


【1】 Varargs 警告

1.1)一個相關問題: 向參數個數可變的方法傳遞一個泛型類型的實例;

  • 1.1.1)考慮以下方法, 它的參數個數是可變的:
public static<T> void addAll(Collection<T) coll, T...ts) {...... }
  • 1.1.2)應該記得, 實際上參數ts 是一個數組, 包含所有實參, 考慮以下調用:
Collection<Pair<String>> table = ......; Pair<String> pair1 = ....; Pair<String> pair2 = ....; addAll(table, pair1, pair2);
  • 1.1.3)為了調用上述方法: java 虛擬機必須建立一個 Pair 數組, 這就違反了前面的規則, 不過, 對于這種case , 你只會得到一個警告, 而不是 錯誤;

1.4)可以采用以下兩種方法來抑制這種警告(Methods):(解決方法)

  • M1)一種方法是 為 包含 addAll 調用的方法增加 標注
@SuppressWarnings("unchecked");
  • M2)在java se 7中, 還可以用 @SafeVarargs 直接標注addAll 方法:
@SafeVarargs public static <T> void addAll(Collection<T> coll, T...ts);
  • 現在就可以用 泛型類型來調用這個方法了;

Annotation)

  • A1)可以使用 @SafeVarargs 標注來消除創建泛型數組的有關限制, 方法如下:
@SafeVarargs static <E> E[] array(E... array) {return array; }
  • A2)現在可以調用:
Pair<String>[] table = array(pair1, pair2);
  • 這看起來方便, 不過隱藏著危險, 如下代碼:
Object[] objarray = table; objarray[0] = new Pair<Employee>();
  • 能順利運行而不會出現 ArrayStoreException 異常 (因為數組存儲只會檢查擦除的類型), 但在處理 table[0] 時 你會在別處得到一個異常;

【2】不能實例化類型變量

2.1)不能使用像 new T(…), new T[…] 或 T.class 這樣的表達式中的類型變量。

  • 2.1.1)看個荔枝:(下面的 Pair 構造器就是非法的)
public Pair() {first = new T();second = new T(); // ERROR }
  • 2.1.2)類型擦除將T 改變成 Object, 而且, 本意肯定不希望調用 new Object()。
  • 2.1.3)但是可以通過反射調用 Class.newInstance 方法來構造泛型對象:
然而,我們卻不能調用: first = T.class.newInstance();//ERROR
  • 2.1.4)因為, 表達式 T.class 是不合法的, 必須像下面這樣設計 API 以便可以支配Class 對象:
public static<T> Pair<T> makePair(Class<T> cl) {try{ return new Pair<>(c1.newInstance(), c1.newInstance()) }catch(Exception ex) {return null;} }
  • 2.1.5)以上方法可以按照下列方式調用:
Pair<String>p = Pair.makePair(String.class);
  • Attention) Class 類本身就是泛型, 如, String.class 是一個 class《String》 的實例(事實上, 它是唯一的實例)。 因此, makePair 方法能夠推斷出 pair 的類型;
  • 2.1.6) 不能構造一個 泛型數組:
public static <T extends Comparable> T[] minmax(T[] a) { T[] mm = new T[2]; ...} //ERROR
  • 類型擦除會讓這個方法永遠構造 Object[2]數組;

2.2)如果數組僅僅是作為一個類的私有實例域, 就可以將這個數組聲明為 Object[], 并且在獲取元素時進行類型轉換。

  • 2.2.1)看個荔枝: 如 ArrayLIst 可以這樣實現:
public class ArrayList<E> {private Object[] elements;...@SuppressWarnings("unchecked")public E get(int n){return (E) elements[n]; //獲取元素時進行類型轉換}pubic void set(int n, E e){elements[n] =e;} }
  • 2.2.2)實際的實現沒有這么清晰:
public class ArrayList<E> {paivate E[] elements;...public ArrayList(){ elements = (E[])new Object[0]; } }
  • 2.2.3)這里, 強制類型轉換 E[] 是一個假想, 而類型 擦除使其無法察覺;

2.3)由于 minmax方法 返回 T[] 數組, 使得這一技術無法施展, 如果掩蓋這個類型會有運行時錯誤。假設實現代碼:

public static <T extends Comparable> T[] minmax(T...a) {Object[] mm = new Object[2];...reutrn (T[]) mm; }

2.4)調用String[] ss = minmax(“tom”, “dick”, “Harry”);
對上述代碼的分析(Analysis):

  • A1)編譯時不會有任何警告。 但Object[] 引用賦給 String[] 變量時, 將會發生 ClassCastException 異常;
  • A2)在這種case下, 利用反射,調用 Array.newIntance;
public static <T extemds Comparable> T[] minmax(T... a) {T[] mm = (T[])mm.newInstance(a.getClass().getComponentType(), 2); }
  • A3)ArrayList 類的toArray方法就沒有這么幸運了。 它需要生成一個 T[] 數組, 但沒有成分類類型。 因此, 有下面兩種不同的形式:
Object[] toArray(); T[] toArray(T[] result);
  • 第二個方法接收一個數組參數。 如果數組足夠大, 就是用這個數組。 否則, 用result 的成分類型構造一個足夠大的 新數組;

總結

以上是生活随笔為你收集整理的java泛型程序设计——Varargs 警告+不能实例化类型变量的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。