关于Java泛型推断,希望大牛不吝赐教

当我成回忆 发布于 2015/06/06 14:20
阅读 491
收藏 1
请教大牛一个问题,希望不吝赐教,关于泛型的推断:当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型,且没有使用返回值,这时候取多个参数中的最大交集类型
例:下面语句实际对应的类型就是Number了,编译没问题,只是运行时出问题。
public static void test(T[] array, T b) {
for (int i = 0; i < array.length; i++){
array[i] = b;
}
}
调用:test(new Integer[3],new Float(1));
既然推断出来T是Number了,为什么还会出现问题了?
加载中
0
如比如比
如比如比

我等鼠辈不敢牛。public static void test(T[] array, T b) {的定义说明T是一个类型

Integer extends Number

Float extends Number的最近共同类是Number所以就按照Number处理了,但是实例分别是Integer ,Float ,这就有问题了,你把Float的值放到Integer的数组里,那是不行的。

当我成回忆
当我成回忆
大侠谦虚了,我就疑问在这里,难道推断出来的Number是摆看的?为什么传进来的实参还是按实参类型处理,没用按照推断出来的类型处理吗?
0
如比如比
如比如比

超速了,@红薯大哥让到引用这儿来。

回复 @当我成回忆 : 这便是抽象和接口的妙处所在,在实例化的时候,父类和自己的东东都被分配了,用父类的变量作强制接受时,只能保存父类的那部分信息,子类的都丢了。兄弟等同宗类之间的保存是不可能的,因为各自那部分不能进行转换。泛型只是把类型广泛化了,你在这里指定Number型的话,那只能用与Number了,给Comparable型的怎么办,再写一个?为了体现OOP的代码重用,引入泛型,并不意味这泛型就作了型变换了。有些罗嗦请原谅。


当我成回忆
当我成回忆
非常感谢您的详细解答,我好好消化下,再次感谢
0
终曲
终曲

这个问题和泛型没什么关系,你把new Float(1)换成"test"字符串是一样的,没有推断Number这回事,这个情况里编译器根本不在意你传的是什么类型,T会被擦除,所以不会有编译错误

最终的类型还是由你传的参数决定,array就是一个Integer[]指针,b就是一个Float指针,Float放进Integer数组显然会有运行时错误

补充一句:T的作用可以看作给编译器静态检查用的,如果你定义

public static <T extends Number> void test(T[] array, T b)

那么就传入字符串就会报错,但是在编译结束后的字节码里是没有T的信息的,具体参考类型擦除机制

0
公孙二狗
公孙二狗

简单点说就是 T[] array 编译后是 Object[] array,Java的范型有个概念叫类型擦除

0
如比如比
如比如比

我认为这个问题和类型擦除是无关的,不服来辩。

类型擦除是编译阶段的技术手段,他这里编译时没有问题。在执行阶段出问题了,那么泛型怎么解释?只能用实际的Java类型来解释,也就是发生ArrayStoreException的原因。


0
GITTODO
GITTODO
就是定义那个样子,JVM在加载允许时才会根据当前T类型,分配内存空间。
0
十年德芙
这错误典型的因为泛型擦除引起的 这种情况应该用泛型语法 比如 super 或 extend 限定一下
0
drongHua
drongHua

引用来自“茶壶”的评论

我等鼠辈不敢牛。public static void test(T[] array, T b) {的定义说明T是一个类型

Integer extends Number

Float extends Number的最近共同类是Number所以就按照Number处理了,但是实例分别是Integer ,Float ,这就有问题了,你把Float的值放到Integer的数组里,那是不行的。

说的很对,public static void test(T[] array, T b)这时的T只能是一个类型,要么是Integer,要么是Float
0
vvtf
vvtf
<? extends Number>
0
Eumenidies
Eumenidies

感觉楼上的都往编译器推断的方向去了,个人感觉不太对啊

首先java的泛型只用作type safe,而不是当模版用的。

然后你的代码明显是错的,把Float放进Integer数组。

因此类型安全的作用就体现了,运行时报错。

返回顶部
顶部