作者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/cn.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