JAVA泛型容器的类型检查

    泛型容器是通过指定容器包含对象的类型,由编译器保证对象类型的正确性,在编译阶段就能检查出类型错误。如下列将List<Long>对象longList赋予一个List<GenericTest>对象gtList,会报编译错误。

public class GenericTest   

{

    public static List<Long> longList = Arrays.asList (1L ,2L);

    public static void main(String args[]){

        //下面这条语句编译会报错

       List<GenericTest> gtList=longList ;        

   }            

}

   如果这只是在编译检查,那么我们是否可以绕过编译检查呢?我们先将List<Long>对象longList赋予一个raw List变量rawList,然后再将这个rawList强制类型转换成List<GenericTest>类型。结果编译通过了,并且运行时也没有报错。我们成功地骗过了编译器。

public class GenericTest

{

    public static List<Long> longList = Arrays.asList (1L ,2L);

    public static void main(String args[]){

        List rawList= longList;

        //这个是可以编译通过,成功的骗过了编译器

       List<GenericTest> gtList= rawList; 

    }

}

   接着,如果我们使用List<GenericTest>类型的变量gtList,那会发生什么事。注意gtList引用的容器里面放的实际上是Long类型对象。这会发生什么事,会引用一段错误的内存吗?结果我们发现String result = gtList.get(0).stringValue;语句正确地在运行时抛出 java.lang.ClassCastException异常。分析 main函数的字节码可知, 在该语句之前插入了类型转换检查字节码,导致了这个异常的抛出。看来Java设计者已经考虑到这一点,在泛型容器对象使用前加上了类型检查,防止这样的情况。

public class GenericTest

{

    public static List<Long> longList = Arrays.asList (1L ,2L);

   public StringstringValue ="ss";

    public static void main(String args[]){

        List rawList= longList;

        //这个是可以编译通过,成功的骗过了编译器

       List<GenericTest> gtList= rawList; 

        //会在运行时抛出 java.lang.ClassCastException

        String result =gtList.get (0).stringValue;

    }

}

 

字节码分析如下:

0 getstatic #28<variable/GenericTest.longList> //获得类变量longList, 并放入栈顶

3 astore_1  //将栈顶引用放入第一个本地变量 rawList

4 aload_1 //将第一个本地变量rawList,放入栈顶

5 astore_2 //将栈顶引用放入第二个本地变量tgList,这里我们可以看到将rawList赋值给tgList,没有任何类型检测,所以运行通过

6 aload_2

7 iconst_0

8 invokeinterface #43<java/util/List.get> count 2

13 checkcast #1 <variable/GenericTest> // 检测类型转换,当我们使用容器中对象时,会有类型检测,导致抛出java.lang.ClassCastException

16 getfield #37<variable/GenericTest.stringValue> // 获得实例属性,并放入栈顶

19 astore_3  //将栈顶引用放入第三个本地变量 result

20 return

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。