Re: [問題] Generic 的 cast 問題

看板java作者 (張昱珩)時間10年前 (2014/12/23 14:27), 10年前編輯推噓2(2028)
留言30則, 4人參與, 最新討論串4/6 (看更多)
不好意思再請問,為什麼下面高亮的 (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

12/23 14:31, , 1F
T的關係。而Counter<String> T為String
12/23 14:31, 1F

12/23 14:44, , 2F
請問既然 T 為 String 為什麼還需要 cast?
12/23 14:44, 2F

12/23 14:49, , 3F
覺得是compiler time認得是T。
12/23 14:49, 3F

12/23 14:50, , 5F
搜尋runtime這個單字,應該能找到些什麼。
12/23 14:50, 5F
※ 編輯: changyuheng (36.231.48.191), 12/23/2014 16:31:08

12/24 01:02, , 6F
因為目前你是傳String,所以你覺得有沒有加都沒差,但是如
12/24 01:02, 6F
不太懂這句話的意思。 不過如果紅色部分的 <T> 不加他會 implicitly cast 成 Object,這是原來的問題。

12/24 01:02, , 7F
果你new 的時候傳Int 好了,最後T就變成Int, 可是你的方法
12/24 01:02, 7F

12/24 01:02, , 8F
只能傳String 所以會有問題
12/24 01:02, 8F

12/24 01:04, , 9F
或是你把 eatString 參數也改成 T 應該就不用cast 了
12/24 01:04, 9F
eatString 只是一個例子,像這邊放在同一個 class 裡沒什麼 sense, 真實狀況中 eatString 應該是在另一個 class 裡。 事實上可以不要管架構,我只是想問語法,例子只是隨手創的。 ※ 編輯: changyuheng (220.141.140.113), 12/24/2014 09:40:36

12/24 10:37, , 10F
你說不要管例子,不過你的問題
12/24 10:37, 10F

12/24 10:38, , 11F
就是因為你的例子才要加(String)
12/24 10:38, 11F

12/24 10:38, , 12F
你不要加(String)的話可以寫成這樣
12/24 10:38, 12F

12/24 10:39, , 13F
12/24 10:39, 13F

12/24 12:18, , 14F
本來的問題是,T 應該是傳進去的 String,但不知為
12/24 12:18, 14F

12/24 12:18, , 15F
什麼拿出來是 Object,結果再次 trace 發現應該是因
12/24 12:18, 15F

12/24 12:18, , 16F
為 T 是 Object,原因如上述。因為 T 是 Object,所
12/24 12:18, 16F

12/24 12:18, , 17F
以拿出來要當 String 就只好 cast。紅色的部分補上
12/24 12:18, 17F

12/24 12:18, , 18F
後就可以確保 T 是 String,所以拿出來是 String 不
12/24 12:18, 18F

12/24 12:18, , 19F
用再轉。eatString 當然能改成吃 T,但這不合理,他
12/24 12:18, 19F

12/24 12:18, , 20F
就已經叫做 eatString 了,而且他存在的意義就是作
12/24 12:18, 20F

12/24 12:18, , 21F
為一個要吃 String 的 method 來當範例。
12/24 12:18, 21F
要改 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

12/24 12:58, , 22F
T傳進去和拿出來的都是String阿?哪裡是Object?
12/24 12:58, 22F

12/24 13:34, , 23F
因為 Counter<String> 變成 Counter<Object>。
12/24 13:34, 23F

12/24 15:18, , 24F
我print出來是String不是Object
12/24 15:18, 24F

12/24 15:55, , 25F
runtime物件是String,但是對compiler的型態檢查是Object
12/24 15:55, 25F

12/24 19:17, , 26F
所以原Po說的是在runtime吧?
12/24 19:17, 26F

12/24 19:17, , 27F
不過我看都是String
12/24 19:17, 27F

12/24 19:33, , 28F
要加(String)才能compile當然是指compile time...
12/24 19:33, 28F

12/24 19:34, , 29F
是說原po都寫了問題是setMember的回傳type之前少了<T>
12/24 19:34, 29F

12/24 19:36, , 30F
你要重現問題去試記得先把那個<T>拿掉....
12/24 19:36, 30F
文章代碼(AID): #1KcGja14 (java)
文章代碼(AID): #1KcGja14 (java)