Re: [J2SE] 宣告 Set<String> edge[] 出了錯誤訊息
※ 引述《tailsice (tailsice)》之銘言:
: 請教各位前輩
: 小弟我最近寫了一支程式
: 裡面有段宣告是這樣寫的
: Set<String> edge[] = new HashSet[in + 1
: for (int i = 0; i < edge.length; i++
: edge[i] = new HashSet<String>();
: 在後面的 new HashSet[in + 1] 為什麼會出
: Type safety: The expression of type HashSet[] needs unchecked conversion
: to conform to Set<String>[]
: 這樣的錯誤訊息呢?
: 我上網苦尋不到答案
: 所以前往跟各位前輩請教
Java 不允許 generic array,因此你只能不告訴 compiler type parameter 是什麼,
但就是因為沒有宣告,所以有 type safety 的 warning。
首先,在 runtime 時,generic 的 type parameter 是不存在的,這叫 tyep erasure,
對原因有興趣的話可以去找資料讀。
接著談一下 covariant 和 invariant 。
array 和一般的 Java 物件一樣為 covariant,可以用 supertype 來 reference
subtype,但也因為如此,它需要清楚的知道物件的 type。
String[] strings = new String[2];
Object[] objects = strings; // okay
可是一個 generic 並不是 covariant。在 runtime 中,type parameter會因為 type
erasure 而不存在,所以 compiler 並不會讓你用 type parameter 的 supertype 來
reference。
ArrayList<String> list = new ArrayList<String>();
ArrayList<Object> anotherList = list; // error
==================================================================
上述觀念與不允許 generic array 的關連 ? 請看下面兩個範例
Example 1 :
1 String[] strings = new String[2];
2 Object[] objects = string;
3 objects[0] = new Integer(1); // ArrayStoreException
上面第三行會錯是因為 objects reference 的畢竟還是一個 String[],
String[] 當然不可以存 Integer,在 runtime 時,這種 type 錯誤會被抓出來。
那如果 generic array 的話呢 ?假設 Java compiler 允許你這樣做
1 ArrayList<String>[] lists = new ArrayList<String>[2]; // 假設可以
2 Object[] objects = lists;
3 ArrayList<Integer> integers = new ArrayList<Integer>();
4 integers.add(1);
5 objects[0] = integers;
6 String string = lists[0].get(0); // ClassCastException
第二行是因為 covariant 的關係,因此可以如此指定,但第五行 code 理論上應該要和第
一個例子一樣會出現錯誤,但其實並不會,因為 type parameter 在 runtime 並不存在,
因此 objects 裡面只剩 ArrayList[],所以 ArrayList<Integer> 當然可以被加到
ArrayList[] 裡面,因為 ArrayList<Integer> 滿足 ArrayList 這個 type check。
下場就是runtime時出現第六行的錯誤。為了type safe,因此打從語法上,compiler
就不準你這樣宣告。
這算是 Java 為了 generic 而導致出的一個大缺陷吧,而且不太直覺。
更詳細的解說可以讀讀這篇
www.angelikalanger.com/Articles/Papers/JavaGenerics/ArraysInJavaGenerics.htm
解法 ? Set<Set<String> 應該比較最穩的方式,也考慮到了 type safe。
雖然很醜,也不易使用,有必要的話,也可以考慮把這種資料結構用物件包起來。
--
We who cut mere stones must always be envisioning cathedrals.
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 114.35.186.241
推
08/30 10:03, , 1F
08/30 10:03, 1F
→
08/30 15:14, , 2F
08/30 15:14, 2F
→
08/30 20:23, , 3F
08/30 20:23, 3F
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 2 篇):
java 近期熱門文章
PTT數位生活區 即時熱門文章