泛型容器类的固有风险

泛型容器类使用不当可能导致类型错误。虽然编译器能防止一些类型不匹配,但运行时由于多态性仍存在风险。示例中,直接赋值可能导致运行时异常,而通过装箱操作的写法能提供一定的安全性,但并不能完全消除风险。程序员需谨慎编写代码以避免这类问题。
摘要由CSDN通过智能技术生成

泛型容器类的固有风险

先看一个例子(例1):

import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        List list1 = new ArrayList<String>();
        List list2 = new ArrayList<Integer>();
        
        /**
		 *这里赋值并不会报错,因为类型安全性检查是针对引用的,list1和list2的引用类型都是ArrayList类型        
		 *上面两句的写法本质上等同于:List list1 = new ArrayList();这种写法
         */
        list1 = list2;
        
        //下面的add也不会报错,这是因为list1的编译时类型还是List,但是当访问元素时发生了类型不匹配			 的错误
        list1.add(1);
        list1.add(3);
        list1.add(3.14);
        
        //这里编译器会提示类型错误:返回的是Object类型(类型擦除),接收的是int类型
        int s = list1.get(0); 
        System.out.println(list1.get(0));
    }
}

上面这种写法显然会发生类型错误。

下面这种写法是较为稳妥的(例2):

import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        //在定义list1,list2的时候就确定编译时类型,运行时类型可以由编译器自行推断(显式声明也可)
        List<Integer> list1 = new ArrayList();
        List<Integer> list2 = new ArrayList();
		
        list1 = list2;
        
        //这里添加 list1.add("1"); 这种不同类型的元素会编译器会报告类型匹配错误
        list1.add(1);
        
        //可以正确赋值
		int a = list1.get(1);
		
		//输出1
        System.out.println(a);
    }
}

为什么说上一种写法是 较为稳妥的呢?
因为虽然避免了因泛型中类型不同而产生的编译时错误,但是运行时类型错误还是存在的(主要是因为多态性的运行时决定实际类型的机制导致的)。

再看下面的例子(例3):

import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        //ArrayList实现了List接口
        List<Integer> list1 = new ArrayList();

        ArrayList list2 = new ArrayList();
        list2.add("1");
        
        //ArrayList实现了List接口,所以赋值操作编译器不会报错,但类型错误已产生(以一种相对隐蔽的方式)
        list1 = list2;
        
        //list1编译期类型是Integer,所以下面的赋值不报错
        int a = list1.get(0);
        
        System.out.println(a);
    }
}

运行程序后产生的错误信息如下:

E:\JDK8\bin\java.exe ...
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
	at com.youkeda.test.Test.main(Test.java:16)

Process finished with exit code 1

相较于例1,例3的错误是无法被编译器发现的,这是因为编译时的类型检查没有问题,然而运行时的实际类型是ArrayList(多态性)。
综上所述,泛型容器类赋值风险仅靠编译器和语言约束是不可避免的,要靠程序员编写程序时小心出现此类错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值