关于泛型,有个地方不明白

lovetysx 2009-09-12 10:28:25
书上说java的泛型是用“擦除法”实现的,也就是编译器进行类型转换,所以编译后的字节码没有类型信息
于是下面的代码编译不通过:

public void test(ArrayList<Integer> al) {
}

public void test(ArrayList<String> al) {
}


这一点我能明白,但是加上返回值了就能编译通过,像下面这样。这是为什么?

public Integer test(ArrayList<Integer> al) {
return null;
}

public String test(ArrayList<String> al) {
return null;
}
...全文
432 39 打赏 收藏 转发到动态 举报
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
dujun3245350 2009-09-15
  • 打赏
  • 举报
回复
接分
pigjavalife 2009-09-14
  • 打赏
  • 举报
回复
pigjavalife 2009-09-14
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 pigjavalife 的回复:]

证明一些ZangXT的观点
[/Quote]
pigjavalife 2009-09-14
  • 打赏
  • 举报
回复

证明一些ZangXT的观点
billhepeng 2009-09-14
  • 打赏
  • 举报
回复
所以和定义的方法是没有直接关系的,是方法定义错误.
billhepeng 2009-09-14
  • 打赏
  • 举报
回复
public void test(ArrayList<Integer> al) {
}

public void test(ArrayList<String> al) {
}
Duplicate method test(ArrayList<String>) in type T1
两个方法同名了.



public Integer test(ArrayList<Integer> al) {
return null;
}

public String test(ArrayList<String> al) {
return null;
}
方法有不同的返回值是当作两方法处理.


ArrayList<Integer> al 和泛型没关系.你只是泛型里面的参数,没有对方法和类作泛型
welllit 2009-09-14
  • 打赏
  • 举报
回复
帮顶一下。
haojia0716 2009-09-14
  • 打赏
  • 举报
回复
http://www.diybl.com/course/3_program/java/javaxl/20071220/92738.html

看这篇文章就知道了

jdk5以后的新特性
ZangXT 2009-09-14
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 spiniper 的回复:]
其实我一直想知道,为什么编译时期总是要与运行时期有这么大差别呢?
为什么编译时期不能够支持不同返回参数的重载?
[/Quote]
怎么确定调用哪一个呢?

比如 String test(int );
void test(int);
如果只想利用方法的副作用而不使用返回值,直接使用test(5)调用,编译器没有办法选择到底调用哪个吧
kunpp 2009-09-14
  • 打赏
  • 举报
回复
会被认为参数类型一样而不能通过
刚写错了
kunpp 2009-09-14
  • 打赏
  • 举报
回复
public void test(ArrayList<Integer> al) {
}
public void test(ArrayList<String> al) {
}
会被认为参数类型不一样而不能通过
改变参数类型或返回值类型就可以了
haojia0716 2009-09-13
  • 打赏
  • 举报
回复
说实话java的泛型设计得不是很好
和以前一些api的兼容性也不是很好
ZangXT 2009-09-13
  • 打赏
  • 举报
回复
首先,jvm一直是支持签名相同但返回类型相同的方法存在的。但java语言级别不支持这种东西。比如
String void test();
int void test();
调用test()的时候,编译器无法确定到底是调用哪个。当然,特定情况下可以通过返回类型推断,这是语言设计者的选择了。

其次,在泛型情况下,不过最终实现使用的是擦除还是别的技术,起码在编译阶段,我们能够通过类型信息确定调用那个方法。
比如
public Integer test(ArrayList<Integer> al) {
return null;
}

public String test(ArrayList<String> al) {
return null;
}
这两个方法,我们可以根据参数来确定调用的方法,在java语言的层次上,参数类型不同,我们可以称之为重载。而且编译之后,得到的是签名相同,但返回类型不同的两个方法。上面我们已经说过,jvm本身就支持这种情况。所以是没有问题的。
为什么
public void test(ArrayList<Integer> al) {
}

public void test(ArrayList<String> al) {
}
不行呢?
如果允许的话,那两个方法就是签名相同且返回类型也相同的了,也就是说两个方法的限定信息完全相同,这jvm就是不支持的了。所以编译器要对这种情形进行限制了。
jayqean 2009-09-13
  • 打赏
  • 举报
回复
泛型用来防止往集合中乱添加对象 (可把错误弄到编译时,而不是运行时)
等待高手的回答
TzSword 2009-09-13
  • 打赏
  • 举报
回复
[Quote=引用楼主 lovetysx 的回复:]
书上说java的泛型是用“擦除法”实现的,也就是编译器进行类型转换,所以编译后的字节码没有类型信息
于是下面的代码编译不通过:
Java code
publicvoid test(ArrayList<Integer> al) {
}
publicvoid test(ArrayList<String> al) {
}

这一点我能明白,但是加上返回值了就能编译通过,像下面这样。这是为什么?
Java code
public Integer test(ArrayList<Integer> al) {returnnull;
}
public String test(ArrayList<String> al) {returnnull;
}
[/Quote]

上面的它统统认为是ArrayList集合类型--所以参数一样---报错
写成这样就不报错了(⊙o⊙)哦!!!
publicvoid test(Integer al) {
}
publicvoid test(String al) {
}
下面的就不用说了,返回值不同
wal812834184 2009-09-13
  • 打赏
  • 举报
回复
高手!
yuhongpingimu 2009-09-13
  • 打赏
  • 举报
回复
String void test();
int void test();
大侠们,这是什么意思?
bayougeng 2009-09-13
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 norwolfli 的回复:]
泛型是编译的时候进行检查的,也就是说使用或者不使用泛型,编译之后生成的.class是一样的.

至于你说的上面的通不过编译,下面的可以,是因为上面的两个方法签名完全相同,所以不行.下面两个返回值类型不同,会当作两个方法处理.如果你把下面两个返回值类型写成相同的,照样通不过.
这个和泛型没有关系,你把泛型去掉,结果是一样的.
[/Quote]
下面的代码是可以通过编译的:

public Integer test(ArrayList<Integer> al) {
return null;
}

public String test(ArrayList<String> al) {
return null;
}

但是,改成下面的样子:

public Integer test(ArrayList al) {
return null;
}

public String test(ArrayList al) {
return null;
}

也就是去掉泛型之后,按照你的理解的话,应该是不会报错的。因为返回值不同,可以认为是两个方法。
事实是,改完以后报错了。编译认为是重复的方法定义。
这个又应该怎么理解呢?
树成 2009-09-13
  • 打赏
  • 举报
回复
其实我一直想知道,为什么编译时期总是要与运行时期有这么大差别呢?
为什么编译时期不能够支持不同返回参数的重载?
24K純帥 2009-09-13
  • 打赏
  • 举报
回复
学习,我也不明白
加载更多回复(19)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧