作者changyuheng (張昱珩)
看板java
標題Re: [問題] Generic 的 cast 問題
時間Tue Dec 23 14:27:45 2014
不好意思再請問,為什麼下面高亮的
(String) 一定要寫?
public class Counter<T> {
private T mEmber;
public Counter
<T> setMember(T member) {
mEmber = member;
System.out.println("setMember(): " + mEmber.getClass().getName());
return this;
}
@SuppressWarnings("unchecked")
public T getMember() {
System.out.println("getMember(): " + mEmber.getClass().getName());
System.out.println("getMember(): "
+ ((Class<T>) mEmber.getClass()).getName());
return (T) mEmber;
}
public static void eatString(String s) {
System.out.println("eatString(): " + s);
}
public static void main(String[] args) {
new Counter<String>().setMember("Java");
eatString(
(String) new Counter<String>().setMember("Java")
.getMember());
}
}
--
UPD: 抱歉,因為本來紅色的地方沒加,加上就好了。
--
http://changyuheng.github.io/
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 36.231.48.191
※ 文章網址: http://webptt.com/m.aspx?n=bbs/java/M.1419316068.A.044.html
※ 編輯: changyuheng (36.231.48.191), 12/23/2014 14:28:25
1F:推 bleed1979: T的關係。而Counter<String> T為String 12/23 14:31
2F:→ changyuheng: 請問既然 T 為 String 為什麼還需要 cast? 12/23 14:44
3F:推 bleed1979: 覺得是compiler time認得是T。 12/23 14:49
5F:→ bleed1979: 搜尋runtime這個單字,應該能找到些什麼。 12/23 14:50
※ 編輯: changyuheng (36.231.48.191), 12/23/2014 16:31:08
6F:→ ckvir: 因為目前你是傳String,所以你覺得有沒有加都沒差,但是如 12/24 01:02
不太懂這句話的意思。
不過如果紅色部分的 <T> 不加他會 implicitly cast 成 Object,這是原來的問題。
7F:→ ckvir: 果你new 的時候傳Int 好了,最後T就變成Int, 可是你的方法 12/24 01:02
8F:→ ckvir: 只能傳String 所以會有問題 12/24 01:02
9F:→ ckvir: 或是你把 eatString 參數也改成 T 應該就不用cast 了 12/24 01:04
eatString 只是一個例子,像這邊放在同一個 class 裡沒什麼 sense,
真實狀況中 eatString 應該是在另一個 class 裡。
事實上可以不要管架構,我只是想問語法,例子只是隨手創的。
※ 編輯: changyuheng (220.141.140.113), 12/24/2014 09:40:36
10F:→ ckvir: 你說不要管例子,不過你的問題 12/24 10:37
11F:→ ckvir: 就是因為你的例子才要加(String) 12/24 10:38
12F:→ ckvir: 你不要加(String)的話可以寫成這樣 12/24 10:38
14F:→ changyuheng: 本來的問題是,T 應該是傳進去的 String,但不知為 12/24 12:18
15F:→ changyuheng: 什麼拿出來是 Object,結果再次 trace 發現應該是因 12/24 12:18
16F:→ changyuheng: 為 T 是 Object,原因如上述。因為 T 是 Object,所 12/24 12:18
17F:→ changyuheng: 以拿出來要當 String 就只好 cast。紅色的部分補上 12/24 12:18
18F:→ changyuheng: 後就可以確保 T 是 String,所以拿出來是 String 不 12/24 12:18
19F:→ changyuheng: 用再轉。eatString 當然能改成吃 T,但這不合理,他 12/24 12:18
20F:→ changyuheng: 就已經叫做 eatString 了,而且他存在的意義就是作 12/24 12:18
21F:→ changyuheng: 為一個要吃 String 的 method 來當範例。 12/24 12:18
要改 eatString 的話,因為他應該是在另一個 class 裡,所以應該吃另一個 type。
像是:
public static <TT> void eatSomething(TT t) {
System.out.println("eatSomething(): " + t.toString());
}
Counter.<Integer>eatSomething(new Counter<String>().setMember("123")
.getMember());
※ 編輯: changyuheng (36.231.48.191), 12/24/2014 12:53:25
22F:→ ckvir: T傳進去和拿出來的都是String阿?哪裡是Object? 12/24 12:58
23F:→ changyuheng: 因為 Counter<String> 變成 Counter<Object>。 12/24 13:34
24F:→ ckvir: 我print出來是String不是Object 12/24 15:18
25F:→ ssccg: runtime物件是String,但是對compiler的型態檢查是Object 12/24 15:55
26F:→ ckvir: 所以原Po說的是在runtime吧? 12/24 19:17
27F:→ ckvir: 不過我看都是String 12/24 19:17
28F:→ ssccg: 要加(String)才能compile當然是指compile time... 12/24 19:33
29F:→ ssccg: 是說原po都寫了問題是setMember的回傳type之前少了<T> 12/24 19:34
30F:→ ssccg: 你要重現問題去試記得先把那個<T>拿掉.... 12/24 19:36