关于泛型的一个小问题

时间:2021-01-28 17:33:33

  package com.inspirx.mkt;

public class Test<T> {

public T get(Integer i) {

Integer k = i;

return (T)k;
}

public static void main(String[] args) {
Test<String> t = new Test<String>();

t.get(2);
}
}


请问各位大侠以上程序执行为什么不出错,而我把Integer强转成String就出错. 但是以上写法难道不是和强转一个意思吗?
这块不理解了.对泛型了解的不深.请各位前辈指较. 
注:return (T)k; 这句话有黄叹号.不知道为什么有,好像是没用到怎么事的.

9 个解决方案

#1


最后一行改为 String str = t.get(2);试试呢

#2


引用 1 楼 gzc145 的回复:
最后一行改为 String str = t.get(2);试试呢



按楼上写法也没有错.

#3


引用 2 楼 java_pojo 的回复:
引用 1 楼 gzc145 的回复:

最后一行改为 String str = t.get(2);试试呢



按楼上写法也没有错.

是编译没有错.运行出错了.但是,我认为,在调用Get方法的时候,走到return的时候,要转换成T(Stirng)这步就应该出错了.可为什么它没出错..类型依然是Integer

#4


如果不报错才有问题的,你传入的是一个Integer的对象,你却要在方法内强制转成String的,你说会不会报错????

注:return (T)k; 这句话有黄叹号.不知道为什么有,好像是没用到怎么事的.
只是给你个警告,告诉你这里强制转换可能会在运行的时候报错

#5


引用 4 楼 abstruct 的回复:
如果不报错才有问题的,你传入的是一个Integer的对象,你却要在方法内强制转成String的,你说会不会报错????

注:return (T)k; 这句话有黄叹号.不知道为什么有,好像是没用到怎么事的.
只是给你个警告,告诉你这里强制转换可能会在运行的时候报错


按我一开始发的贴子那种写法,编译,运行都没有错.
按1L的写法,是编译无错,运行有错.
但我认为,我的第一种写法运行就应该出错了.但它没出.所以不理解了.

#6


泛型会在编译期执行类型安全检查,但在运行时 泛型将都由于擦出原因被认作是Object,所以此处的T在运行时只是Object不管你是Integer还是S挺都可以,但是强制类型转换时String就是String,Integer就是Integer,所有会出现编译期异常无法执行!记住泛型在运行期间会被擦出类型!

#7


所以由于类型擦出才会有那种所谓的黄叹号!因为编译期在运行期间无法知道其类型!也是因此你的第一种写法才可以运行,在运行期间它等同于return (Object)i;所以再加上String  i = t。get(2);就会出现错误!只能写成Object i = t。get(2);才可以!

#8


看警告就知道是为强制检查的类型转换,有可能运行时抛异常

#9


JAVA的泛型可以说是一种伪泛型,在编译为字节码时会把泛型的类型擦除了,因此
public T get(Integer i) 它的返回类型在编码后变为了Object的类型了,所以它是把Integer强转为Object。

9: iconst_2
10: invokestatic  #4        // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
13: invokevirtual #5       // Method get:(Ljava/lang/Integer;)Ljava/lang/Object;
上面这几行是t.get(2);的字节码,从中可以看出invokevirtual指令执行的get方法的返回类型是Object的,传入参数类型是Integer

#1


最后一行改为 String str = t.get(2);试试呢

#2


引用 1 楼 gzc145 的回复:
最后一行改为 String str = t.get(2);试试呢



按楼上写法也没有错.

#3


引用 2 楼 java_pojo 的回复:
引用 1 楼 gzc145 的回复:

最后一行改为 String str = t.get(2);试试呢



按楼上写法也没有错.

是编译没有错.运行出错了.但是,我认为,在调用Get方法的时候,走到return的时候,要转换成T(Stirng)这步就应该出错了.可为什么它没出错..类型依然是Integer

#4


如果不报错才有问题的,你传入的是一个Integer的对象,你却要在方法内强制转成String的,你说会不会报错????

注:return (T)k; 这句话有黄叹号.不知道为什么有,好像是没用到怎么事的.
只是给你个警告,告诉你这里强制转换可能会在运行的时候报错

#5


引用 4 楼 abstruct 的回复:
如果不报错才有问题的,你传入的是一个Integer的对象,你却要在方法内强制转成String的,你说会不会报错????

注:return (T)k; 这句话有黄叹号.不知道为什么有,好像是没用到怎么事的.
只是给你个警告,告诉你这里强制转换可能会在运行的时候报错


按我一开始发的贴子那种写法,编译,运行都没有错.
按1L的写法,是编译无错,运行有错.
但我认为,我的第一种写法运行就应该出错了.但它没出.所以不理解了.

#6


泛型会在编译期执行类型安全检查,但在运行时 泛型将都由于擦出原因被认作是Object,所以此处的T在运行时只是Object不管你是Integer还是S挺都可以,但是强制类型转换时String就是String,Integer就是Integer,所有会出现编译期异常无法执行!记住泛型在运行期间会被擦出类型!

#7


所以由于类型擦出才会有那种所谓的黄叹号!因为编译期在运行期间无法知道其类型!也是因此你的第一种写法才可以运行,在运行期间它等同于return (Object)i;所以再加上String  i = t。get(2);就会出现错误!只能写成Object i = t。get(2);才可以!

#8


看警告就知道是为强制检查的类型转换,有可能运行时抛异常

#9


JAVA的泛型可以说是一种伪泛型,在编译为字节码时会把泛型的类型擦除了,因此
public T get(Integer i) 它的返回类型在编码后变为了Object的类型了,所以它是把Integer强转为Object。

9: iconst_2
10: invokestatic  #4        // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
13: invokevirtual #5       // Method get:(Ljava/lang/Integer;)Ljava/lang/Object;
上面这几行是t.get(2);的字节码,从中可以看出invokevirtual指令执行的get方法的返回类型是Object的,传入参数类型是Integer