通过例子体现泛型擦除特性

通过Spring拷贝方法演示

1、演示代码

定义了公用的泛型拷贝对象(源对象和目标对象),里面包含list的泛型属性;

import org.springframework.beans.BeanUtils;

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

class CopyObj<T> {
    private List<T> list;

    public List<T> getList() {
        return list;
    }

    public void setList(List<T> list) {
        this.list = list;
    }
}

/**
 * @author Green
 * @date 2021年12月31日 11:11 上午
 */
public class CopyTest {

    public static void main(String[] args) {
        // 定义包含List<String>属性的源对象
        CopyObj<String> strCopyObj = new CopyObj<>();
        List<String> stringList = new ArrayList<>();
        stringList.add("abc1");
        stringList.add("abc2");
        stringList.add("abc3");
        strCopyObj.setList(stringList);

        // 定义包含List<Integer>属性的目标对象
        CopyObj<Integer> intCopyObj = new CopyObj<>();
        List<Integer> integerList = new ArrayList<>();
        intCopyObj.setList(integerList);
        // 通过spring拷贝对象,只要属性名和属性类型能够对应上都会进行拷贝
        // 运行时泛型擦除了,所以泛型对不上并不影响
        // 两个对象中都包含名为list 类型为java.util.List 的属性,所以这两个属性会进行拷贝
        // 但是拷贝之后目标对象intCopyObj中存储的是源对象strCopyObj中属性list的值,
        // 也就是讲string类型的值拷贝到了intCopyObj对象中的List<Integer>类中属性中
        // 拷贝可成功,因为泛型擦除,实际拷贝进的属性类型是List
        BeanUtils.copyProperties(strCopyObj, intCopyObj);   // 这里是拷贝
        // 但是这里遍历会出问题,因为编译时会检测泛型,
        // 要想编译通过,目标对象的属性编译时是Integer类型,但实际运行是这里存储的是String类型
        // 所以这里遍历会报错类型转换异常
        for (Integer integer : intCopyObj.getList()) {
            System.out.println("success!");
        }
    }
}

 

2、debug详情

拷贝是可以完成的,目标对象intCopyObj中属性List<Integer> 会存储三个String类型的值,如下:

 

但是下一步遍历的时候会报错,String不能转换为Integer,如下图:

 

 原因:这就是因为泛型在编译期有效,在运行期擦除了,可以通过反射赋值而不受泛型限制,但是后面的调用运行期会报错;具体原因可以看第一部分的代码注释; 

 

 

posted @ 2021-12-31 11:37  迷走神经  阅读(98)  评论(0编辑  收藏  举报