看板 java 關於我們 聯絡資訊
不好意思再請問,為什麼下面高亮的 (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://www.ptt.cc/bbs/java/M.1419316068.A.044.html ※ 編輯: changyuheng (36.231.48.191), 12/23/2014 14:28:25
bleed1979: T的關係。而Counter<String> T為String 12/23 14:31
changyuheng: 請問既然 T 為 String 為什麼還需要 cast? 12/23 14:44
bleed1979: 覺得是compiler time認得是T。 12/23 14:49
bleed1979: 搜尋runtime這個單字,應該能找到些什麼。 12/23 14:50
※ 編輯: changyuheng (36.231.48.191), 12/23/2014 16:31:08
ckvir: 因為目前你是傳String,所以你覺得有沒有加都沒差,但是如 12/24 01:02
不太懂這句話的意思。 不過如果紅色部分的 <T> 不加他會 implicitly cast 成 Object,這是原來的問題。
ckvir: 果你new 的時候傳Int 好了,最後T就變成Int, 可是你的方法 12/24 01:02
ckvir: 只能傳String 所以會有問題 12/24 01:02
ckvir: 或是你把 eatString 參數也改成 T 應該就不用cast 了 12/24 01:04
eatString 只是一個例子,像這邊放在同一個 class 裡沒什麼 sense, 真實狀況中 eatString 應該是在另一個 class 裡。 事實上可以不要管架構,我只是想問語法,例子只是隨手創的。 ※ 編輯: changyuheng (220.141.140.113), 12/24/2014 09:40:36
ckvir: 你說不要管例子,不過你的問題 12/24 10:37
ckvir: 就是因為你的例子才要加(String) 12/24 10:38
ckvir: 你不要加(String)的話可以寫成這樣 12/24 10:38
ckvir: http://ppt.cc/QCh4 12/24 10:39
changyuheng: 本來的問題是,T 應該是傳進去的 String,但不知為 12/24 12:18
changyuheng: 什麼拿出來是 Object,結果再次 trace 發現應該是因 12/24 12:18
changyuheng: 為 T 是 Object,原因如上述。因為 T 是 Object,所 12/24 12:18
changyuheng: 以拿出來要當 String 就只好 cast。紅色的部分補上 12/24 12:18
changyuheng: 後就可以確保 T 是 String,所以拿出來是 String 不 12/24 12:18
changyuheng: 用再轉。eatString 當然能改成吃 T,但這不合理,他 12/24 12:18
changyuheng: 就已經叫做 eatString 了,而且他存在的意義就是作 12/24 12:18
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
ckvir: T傳進去和拿出來的都是String阿?哪裡是Object? 12/24 12:58
changyuheng: 因為 Counter<String> 變成 Counter<Object>。 12/24 13:34
ckvir: 我print出來是String不是Object 12/24 15:18
ssccg: runtime物件是String,但是對compiler的型態檢查是Object 12/24 15:55
ckvir: 所以原Po說的是在runtime吧? 12/24 19:17
ckvir: 不過我看都是String 12/24 19:17
ssccg: 要加(String)才能compile當然是指compile time... 12/24 19:33
ssccg: 是說原po都寫了問題是setMember的回傳type之前少了<T> 12/24 19:34
ssccg: 你要重現問題去試記得先把那個<T>拿掉.... 12/24 19:36