这几天在看泛型,觉得越看越怪 首先 这个泛型变量在编译时候哦会被擦除 那么就会用其原始类型去替代,若是无限制类型的话  就用object  但是这样的话  实际应用中又怎么知道该变量 会是尖括号中份额类型参数的类型 ~~~~ 不知道编译器在这块做了什么

解决方案 »

  1.   

    如果是Object的话  实际中会强制转换为你需要的类型
      

  2.   

    ~~可能没说清楚吧~~ 就是java虚拟机对待泛型的话     比如class  pair<T>{ T r;}
    这个类  在编译时候虚拟机会把其T给擦除  类用一个原始类型代替即pair类型   而变量r  则变为Object类型的变量  (没有给予限定类型的话)   那么我在主方法中使用pair<String> a=new pair<String>  它又能识别出尖括号中的类型参数,  我想问的是  明明编译都成了object  到了主方法调用时候又是如何识别并转换为相应类型  我有点不理解 用了javap 查看字节码 也还是不很理解 我所看到的 全是object~~~类型          
      

  3.   

    楼主说的没错,Thinking in java里也有相关的证明,擦除确实将方法或类内部的实际信息去除掉。但是编译器会留个记号,也就是边界处理。在对象进入并且离开方法的时候做个记号,进行二次编译,也就是说一旦进入该方法,编译器会进行类型检查,然后离开方法的时候会对值进行强制类型转换。
      

  4.   

    JAVA编译器生成代码时会自动加入类型转换或类型检查,如:List<Integer>擦除后变成List,
    当我们执行get()时,编译器会在返回语句上自动加入(Integer)x的操作,将Object转为Integer类型
    同理,当执行add()时,编译器会在方法的一开始添加检查参数是否为Integer的操作,如果不是,则抛出异常。
    建议看下Thinking in Java,里面有很详细的解释。
      

  5.   

    代码: List<Integer> ls = new ArrayList<Integer>();
    ls.add(1);
    Integer i = ls.get(0);javap -c 结果   0:   new     #2; //class java/util/ArrayList
       3:   dup
       4:   invokespecial   #3; //Method java/util/ArrayList."<init>":()V
       7:   astore_1
       8:   aload_1
       9:   iconst_1
       10:  invokestatic    #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       13:  invokeinterface #5,  2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
       18:  pop
       19:  aload_1
       20:  iconst_0
       21:  invokeinterface #6,  2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
       26:  checkcast       #7; //class java/lang/Integer
       29:  astore_2注意第10行和第26行的类型转换。
      

  6.   

    楼上的ma_xupeng说清楚了。其实楼主也明白泛型是编译器行为,而不是JVM行为;
    并且也明白泛型是JDK5中引入的,以前的版本是没有泛型机制的;
    那泛型擦除,用一个原始类型代替,如何识别并转换为相应类型?那如果没有泛型,要进行类型转换,在以前的老版本中,楼主肯定会很容易的知道,是用强制类型转换来进行类型转换的,就是在要转换的类型前加个()和转换类型。既然JDK5中不需要强制类型转换,那总要有个地方来转换,因为JVM是和以前的行为一致的,这就明白了,是编译器做了处理,以前程序中强制类型转换的代码现在由编译器来生成,这样我们写的代码即美观又方便,还减少了错误(如果仅仅是为了美观、方便,那不能说是个显著的特性了),提高了类型转换安全性。编译器怎样编译泛型表达式和泛型方法:
    编译泛型表达式,如果返回类型擦除,编译器会插入强制类型转换。
    而泛型方法类型擦除有时会很复杂,像多态中,常会合成桥方法来保持多态。
    楼主可以再看看相关书籍详细了解,看编译器会怎样处理。
    最好的是用个老版本的编译器生成class,然后用JDK5或之后的版本生成一份class,对照一下。其实保证了程序的正确性,编译器还可以优化代码。
      

  7.   

            List<Integer> ls = new ArrayList<Integer>();
            ls.add(1);
            Integer i = ls.get(0);
    这就是一个很典型的泛型的例子,不知道楼主想要什么结果
      

  8.   

    这里有自动装箱啊,add 进去的还是一个 Integer
      

  9.   

    ma_xupeng的回复很好,感觉关键还是得从编译器编译的字节码上去看。