黑马程序员技术交流社区

标题: 看看吧,我脑子短路了 [打印本页]

作者: 伍仪华    时间: 2011-7-29 18:23
标题: 看看吧,我脑子短路了
import java.util.*;
public class Text
{
public static void append(List list)
{
list.add("0042");
}
public static void main(String[] agrs)
{
  List<Integer> intList = new ArrayList<Integer>();
  append(intList);
  System.out.println(intList.get(0));
}
}
为什么输出的是0042?
“0042”应该是String的
但是List<Integer> intList 这里要求的是Integer的,请各位高手指点
作者: 匿名    时间: 2011-7-29 18:46
List<Integer> intList要求的是Integer,但是你插入的实际上是String类型的对象,所以intList.get(0)得到的类型不是Integer,而是String类型。如果你用Integer a = intList.get(0);编译器就会报错,抛出异常。
所以从集合提取对象句柄时,必须用某种方式准确地记住它们是什么,以保证程序的正常运行。
作者: 匿名    时间: 2011-7-29 19:49
这个问题,其实也是由于“泛型绕过了编译器”而引起的。
仔细看看ArrayList<E>的源代码,虽然这个类使用了泛型,但是保存数据的数组,确是Object类型的。[code=java]private transient Object[] elementData;[/code]最初,您的代码为:[code=java]List<Integer> intList = new ArrayList<Integer>(); [/code]定义一个List<Integer>的变量intList 。 此时intList 的add()方法中仅可以添加Integer类型的对象,否则编译报错。
然后,您的代码为:[code=java]append(intList); [/code]其实就相当于:List list = new ArrayList<Integer>();
换种写法就是:List<?> list = new ArrayList<Integer>();  。此时,其实就擦除了list的泛型。
也就是说,编译器不会再阻止咱们向list中插入String对象了。事实上,现在咱们可以为所欲为,向其内插入任意Object对象。
因此,在您写的append()方法中,咱们成功的将String类型的数据插入到那个名为elementData的Object[]数组之中了。
相应的调用intList.get()方法,就是从Object[]数组中取出数据。
但是,还是有个问题,下面是ArrayList类中get()方法的源代码:[code=java]public E get(int index) {
        RangeCheck(index);
        return (E) elementData[index];
    }[/code]返回值的类型为E类型,在List<Integer> intList中,E为Integer。
但是咱们调用intList.get()方法,却成功返回了一个String类型的对象。好神奇。
上面说的是我个人的意见。


不管你信不信,反正我信了。
作者: 王松朝    时间: 2011-7-29 20:05
调用方法的时候传递的是集合的引用,而新的引用没有限制类型;
请教怎么将泛型类型也一起传进去?
作者: 匿名    时间: 2011-7-29 20:36
只有一个解释:泛型只会编译时起作用,运行时泛型的概念就没了
作者: 匿名    时间: 2011-7-29 21:46
泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一致。
这是张老师教程里面有的呀,兄弟上课睡觉了吧!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2