java中泛型List问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中泛型List问题相关的知识,希望对你有一定的参考价值。

问题:为什么在一个Integer的List里面插入一个String的对象读取成功而在一个String的List插入一个整数读取时抛出ClassCastException?看代码。

以下是在一个Integer的List里面插入一个String对象,读取正确。

public class IteratorTest2
public static void go(List list)

list.add("1.1");

public static void main(String args[])

List<Integer> list=new ArrayList<Integer>();
list.add(1);
go(list);
System.out.println(list.get(1));


------------------------------------------------------------

以下是在一个String的List里面插入一个整型数,读取抛出异常。

public class IteratorTest2
public static void go(List list)

list.add(1.1);

public static void main(String args[])

List<String> list=new ArrayList<String>();
list.add("1");
go(list);
System.out.println(list.get(1));



请高手解析!
两段代码是不同内容的,大家仔细看,还没有人知道答案- -,加油啊,答得好我追加分数

您好,我用断点调试解释吧[真的很高兴能与你讨论][啊啦上回不好意思但还是说对一部分滴].
1-----你在go方法中,没有给list限制泛型约束,所以1.1不加check的存储进arraylist了.

2-----"1.1"是被内部机制转换为Double存储进arraylist的:

[在System.out.println(list.get(1));处下断点,点调试.可以看到list里是
[1, 1.1],
elementData[]为
[1, 1.1, null, null, null, null, null, null, null, null].
elementData[0]的值是"1",
elementData[1]的值为Double (标识=37).]

也就是说,go方法add时因为没有约束,所以由内部机制将1.1转换为Double存入了以String为约束的list里.

3-----点"单步跳入",看到代码跳到了arraylist的get里:
public E get(int index)
RangeCheck(index);

return elementData[index];

关键点就在这了,由第2步看到elementData[1]的类型为Double,而在main里为list设置的约束是String,所以E 为String.上面的代码就变为:
public String get(int index)
RangeCheck(index);

return 1.1; //double

继续跳,
看到他照样返回了一个加着String标签的double值.

4-----继续点然后报错了.这个是由于syso输出是输出String.这个后面会说.

如果你加一个方法:
public static void go1(List list)

System.out.println(list.get(1));

这样没约束的情况下syso,是没有错的.因为get后的对象没有加类型标签,会由内部机制判断他到底是哪个类.
而加了String返回类型标签后就不做判断直接调用syso(String)的方法来输出Double了.所以报告了class cast错误.
如果你继续看,会看到是String类的init出现的错误.
因为前面调试中看到syso(args)的args为String[],而返回的却是Double.类型没匹配上.

正确的那个例子不用说了吧,调试一下会发现他syso时String.valueof(obj)了,"1.1"肯定满足条件.[如果不满足条件,会打印object,这也是能输出syso(list)的原因][SYSO在控制台输出的是字符,如果是double会转为字符输出]

而错的那个因为返回标明了是String,所以程序不加判断就直接write了,输出字符却给个double,就出错了.

上班了...打一中午,555,可能说的有错误,楼主自己调试一下,以自己的方式理解一下吧>_<
PS:其实俺上回说的有一部分对...我楼上那位5级大哥说的也部分对,但1.1是double传进去的,没转换成int.调试过我就明白了,一开始我也那么想.
参考技术A xinflya你的回复不对!

首先double有toString的方法,自己可以查API,其次是在Integer里插入的“1”根本没转换成Integer,你可以试试,如果真的转换成Integer调试的时候System.out.prinln(list.get(1).toString);是正确的,而刚好想法,加了这语句会抛出转换出错异常,可见根本就没在内部自动转换。

huang4953的回复也不对!
在String里插入一个1,会自动转换为Integer类型,同理插入一个1.1也会自动转换成Double类型,因为在List插入的数据不可以是基本数据类型,这点是确定的!

我的看法,在Integer里插入一个“1”,其实就是插入一个String类型的东西,但调用list.get(1)的时候很奇怪,感觉就是没把String转换成Integer就直接输出了,也就是没经过转换。而在String里插入一个其他类型,在list.get(1)的时候经过了转换,而转换不是toString()更像是直接强制转换。说了这么多废话,其实我还是没发现原因,希望下一个朋友能发现!
=================================================================
不单单是插入一个double数据类型后取出来才出错,插入任何一种引用类型,或者包转类,当你拿出来时都是抛出同一个异常,转换出错。我总结一下观点,也是我认为是正确的。

1.当你往链里插入一个基本数据类型,他会转换成所对应的包转类。
2.而在String类型的链里插入任何一种基本数据类型或者除String类型外的引用类型,取出的时候都还出错。

xinflya你认为double转换成一个类时出错,其实不然,当你插入doulbe后在链里就已经是一个包装类了,也就是Double,错误提示是Double不能转换成String.而不是你所说的double转换Double失败。
我把错误贴上来。
java.lang.Double cannot be cast to java.lang.String
问题是:为什么Double不能转换成String?难道真的是强制转换问题?假设成立,那又怎么解释在Integer中的Double强制转换成Integer成功?
参考技术B 数字可以强转成字符串,但是字符串不好强转成数字,忽忽·· 参考技术C 第二个集合中输出为:
System.out.println(list.get(0));
但go方法不会运行所以 不会添加(1.1)这个值
最后输出为添加的1
参考技术D 应该是这样的.go(list);而你这个list里面并没有用<>来约束他,所以他传任何数据类型都可以,像上面的那个正确例子,其实你的泛型是没有起到作用的,如果你要起到只能传Integer,你应该在public static void go(List<Integer> list),加了这约束,你下面就不能传String,,这样泛型才有使用的意义.下面也是一样.至于为什么Integer可以传String进去,而String不能传int进去,这个是因为Integer是int的包装类,它可以接收对象."1.1"传进去是以一个对象传进去的,而不是字符串.下面那个你传一个1.1是一int类型的值传进去的,而他只能接收String类型的值,所以不行.
java的包装类类型:boolean---Boolean,char---Character byte---Byte
short--Short int---Integer long--Long float--Float double---Double
void--Void
你可以下面的string换成这里面任意一个再试试.你想让第二个例子成功就写成
System.out.println(list.toString()); 那个list.add("1")可以去掉,直接打印上面的list的值. 上面这些是java1.5新增的自动装包和拆包

java中泛型的使用

参考技术A 泛型可以避免强制类型转换,设定集合对象中存储的对象类型。
比如List<String> list = new ArrayList<String>();
那在这个list中,只能存储字符串对象。
参考技术B 一般使用在集合上,比如现在将一个字符串类型放在集合里面,这时候,放入集合的字符会失去其本身的类型,只能是object类型,比如想要对这这个值进行转换, 很容易出现类型转换错误。可以使用泛型解决这个问题。 参考技术C

只要了解了泛型的一般使用情况就能够解决多半的问题。

什么是泛型?

试想一个简单的添加方法(method),如下:

long,float 或 double 类型并不能当作输入传给这个方法。

如果从该方法中抽象出数据类型,就可以得到一个新的方式,如下。

在这里,<T>是 泛型参数(也称为类型变量),和给某一方法声明的参数一样。

给 <Integer> 或 <Double> 传递的泛型参数的值,与方法参数相似,叫做类型参数。

以上是关于java中泛型List问题的主要内容,如果未能解决你的问题,请参考以下文章

Java中泛型通配符的一点概念

java中泛型是啥意思,作用是啥?

java中啥叫泛型??

java泛型中的下限

List集合中泛型使用细节

当List的size为0时,如何获取List中泛型的类型