Java泛型详解

本文深入探讨了Java中泛型的作用,如何防止堆污染,以及堆污染产生的原因和后果。通过示例代码,解释了泛型在避免类型转换异常和确保集合安全性方面的关键角色,同时阐述了在参数化可变参数类型中可能出现的堆污染警告。堆污染可能导致ClassCastException,因此理解和正确使用泛型对于编写健壮的Java代码至关重要。
摘要由CSDN通过智能技术生成

为什么需要泛型?

List list = new ArrayList();
list.add("A");
list.add(100);
for (int i = 0; i < list.size(); i++) {
  String name = (String) list.get(i); //取出Integer时,运行时出现异常
System.out.println("name:" + name);
}

使用泛型

List<String> list = new ArrayList<String>();

通过List ,直接限定了list集合中只能含有String类型的元素,集合记住了元素的类型,无需进行强制转换

Heap Pollution

什么是堆污染:
堆污染是一种技术用语,它指的是对象的引用类型不是指向对象类型或者超类类型。

List<A> listOfAs = new ArrayList<>();
List<B> listOfBs = (List<B>)(Object)listOfAs; // 指向as列表,造成堆污染
// 这会导致ClassCastExceptions

所以,当将一个不带泛型的对象赋值给带泛型的变量是,通常会引发堆污染。

什么时候会发生堆污染

把一个不带泛型的对象赋给一个带泛型的变量是,就会发生堆污染. 通常编译期间都会检测出这种情况,并且显示警告: unchecked warning.

List ns = new ArrayList<Number>();
List<String> ls = ns;

为什么会发生堆污染

在Java中,参数化类型(泛型),都是非具体化类型(non-reifiable types)。

non-reifiable types 是指,在runtime时期是不完整的类型,在编译期间,非具体化类型会经过 “类型擦除”(编译器会删除域类型参数相关的信息),所以准确的说,泛型只存在于编译时期。
非具体化类型保证了那些使用JDK1.5(没有泛型)之前的程序的二进制兼容性。

因此,不同泛型的同一类型变量,在运行时具有相同的类或接口实现。所以,当参数化类型的变量(List<String>)指的不是该参数化类型的对象(List<Integer>)时,就发生了堆污染。

Set s = new TreeSet<Integer>();
Set<String> ss = s;            // unchecked warning
s.add(new Integer(42));        // another unchecked warning
Iterator<String> iter = ss.iterator();
while (iter.hasNext())
{
    String str = iter.next();   // ClassCastException thrown
    System.out.println(str);
}

parameterized vararg type 为什么会发生堆污染警告

有如下参数化可变参数类型的方法会发生堆污染警告:

public static <T> void foo(List<T>... bar) {
    for (List<T> ts : bar) {
        System.out.println(ts);
    }
}
// warning: Possible heap pollution from parameterized vararg type

参数化可变参数类型可能发生堆污染,这是因为,可变参数在编译时期,会做出如下转换:

  • public static <T> void foo(List<T>... bar) 函数,被转换为
  • public static <T> void foo(List<T>[] bar),然后再转换为
  • public static <T> void foo(List[] bar)

这样,我们如下调用:

Object[] objectArray = new String[]{};
List<Integer>[] lists = (List<Integer>[]) objectArray;
foo(lists);

就会发生ClassCastException异常,(java.lang.String; cannot be cast tojava.util.List)。所以,会出现堆污染警告。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值