import java.util.ArrayList;public class GenericTest2 { @SuppressWarnings("unchecked")
public static void main(String[] args) { ArrayList<? extends Number> arr = new ArrayList<Integer>();
// ArrayList<? super Integer> arr0 = new ArrayList<Integer>();
// arr.add("5");//不能添加任何类型的对象,上界通配符能获得元素,不允许添加
// Number n = arr.get(0);
// System.out.println(n);
// Integer i = arr.get(0);
// arr0.add(4);//下届通配符能add元素,不允许获得
// arr0.add(4.1);
// Integer i = arr0.get(0); 不能get任何类型的对象
ArrayList<Double> arr1 = (ArrayList<Double>)arr;//能强转
arr1.add(3.14);
// ArrayList<Integer> arr2 = (ArrayList<Integer>)arr1;//不能强转
// ArrayList<Long> arr3 = (ArrayList<Long>)arr;//能强转
// ArrayList<Double> arr4 = (ArrayList<Double>)arr3;//不能强转
}}问题:
1、 ArrayList<? extends Number> arr = new ArrayList<Integer>();这条语句创建的ArrayList是什么类型的?2、 ArrayList<Double> arr1 = (ArrayList<Double>)arr;为什么能够强转?3、 ArrayList<Integer> arr2 = (ArrayList<Integer>)arr1;为什么不能强转? 我知道泛型是一种编译器语言,所以希望大大能够从编译器的角度帮我分析一下,再有就是泛型里面该死的擦除,到底是什么意思,如果能够帮忙解答,万分感谢!!
1、为ArrayList<Integer>类型;
2、3参考://以下由d强制转换为i报错
Double d=new Double(2.0);
Integer i=new Integer(d);
//以下有i2转换为d2通过
Integer i2=new Integer(2);
Double d2=new Double(i2);
至于原因可以参考强制转换规则,另外这跟泛型关系不大,主要是强制转换的问题,什么编译器啊什么的更谈不上了。
以上鄙人愚见,仅供参考。
创建的是ArrayList<? extends Number>类型,arr指向的是一个ArrayList<Integer>实例,即arr里存放的是Integer对象
2、 ArrayList<Double> arr1 = (ArrayList<Double>)arr;为什么能够强转?
因为Double也是Number的子类,而且double的精度比int高,转换时不存在精度自动放大
比如 int a = 10; double b = a; 没问题,精度自动放大
所以ArrayList<Double>可以全体自动转换3、 ArrayList<Integer> arr2 = (ArrayList<Integer>)arr1;为什么不能强转?
因为int的精度比double小,所以double转为int时有精度损失,不能自动转换,必须强行转换
所以ArrayList<Integer>不能全体转换,必须针对集合的元素一个一个强行转换
2,3、 我没太明白您的意思,是不是说只要符合自动类型转换的才能强转,那如果将ArrayList<Double> arr1 = (ArrayList<Double>)arr;//能强转改成ArrayList<Short> arr1 = (ArrayList<Short>)arr;为什么却能够强转?再有麻烦您帮忙讲解一下关于泛型擦除行吗,我实在是没明白?
因为arr是一个ArrayList<? extends Number>类型的引用,而它没有add(int)这个方法可以调用
add(int)方法只有ArrayList<Integer>这个类型可以调用,也就是说add(int)方法不能用父类的引用去调用,只能用子类的引用调用2、
ArrayList<Double> arr1 = (ArrayList<Double>)arr;//能强转
改成
ArrayList<Short> arr1 = (ArrayList<Short>)arr;为什么却能够强转?
因为Short也是Number的子类,所以理由同Double,一样可以转换
我上面说了,创建的是ArrayList<? extends Number>类型,但是arr指向的是一个ArrayList<Integer>实例,即arr里只能存放的Integer对象2
我上面也说了,因为Double也是Number的子类,即<Double>符合<? extends Number>,而arr是ArrayList<? extends Number>类型,所以ArrayList<Double> arr1 = (ArrayList<Double>)arr;可以强行转换3
受了1楼的一些干扰,arr1是ArrayList<Double>类型,而<Integer>不符合<Double>,
所以ArrayList<Integer> arr2 = (ArrayList<Integer>)arr1;不能强行转换
1、 如果为ArrayList<Integer>类型,那么为什么add(5);报错呢?
arr不是ArrayList<Integer>类型,是ArrayList<? extends Number>类型,只是arr指向的是ArrayList<Integer>实例,ArrayList<E>的add(E e)方法里规定,add方法参数只能是和泛型一致的类型,即arr里的add方法参数是个? extends Number类型,而5是Integer,不是? extends Number类型,所以不能存放。可以通过ArrayList<Integer> arrx = (ArrayList<Integer>)arr; arrx.add(5)来达到目的。即先把? extends Number强行转换为Integer,然后再调用add方法,此时参数就是明确的Integer类型了。ArrayList<Double> arr1 = (ArrayList<Double>)arr;//能强转
改成
ArrayList<Short> arr1 = (ArrayList<Short>)arr;为什么却能够强转?
这个问题和2一样,arr是ArrayList<? extends Number>类型,<Short>符合<? extends Number>,所以可以强行转换。
ArrayList<? extends Number> arr = new ArrayList<Integer>();
ArrayList<Integer> arr0 = (ArrayList<Integer>)arr;
arr0.add(5); //存放Integer
ArrayList<Double> arr1 = (ArrayList<Double>)arr;
arr1.add(3.0); //存放Double如果是这样的,感觉
ArrayList<? extends Number> arr = new ArrayList<Integer>();和
ArrayList<? extends Number> arr = new ArrayList<Number>();是等效的,即后面的实现类型是什么都没关系,好像以<? extends Number>优先。这个也没仔细研究过,有时间再看看。
ArrayList<? extends Number> arr = new ArrayList<Integer>();
这里创建的是ArrayList<Integer>类型,它是ArrayList<? extends Number>的子类型;
arr里面元素的实际类型是Integer. 但你这里使用了个 ? 通配符,表示Number的任何子类型,arr无法增加任何具体类型元素,即add(具体类型);只能arr.add(null); 原因就是这里类型变量<? extends Number>告诉编译器保存的元素类型是Number的任何子类型,编译器无法确认。(是不是很别扭的)ArrayList<Double> arr1 = (ArrayList<Double>)arr;
这里其实是转换为子类型,ArrayList<Double>是ArrayList<? extends Number>的子类型,当然能过强制转换。ArrayList<Integer> arr2 = (ArrayList<Integer>)arr1;
这里主要是ArrayList<Integer>和ArrayList<Double>没有任何关系,虽然Integer和Double同是Number的子类型,但ArrayList<Integer>)或ArrayList<Double>并不是ArrayList<Number>的子类型,所以明显ArrayList<Double>不能强制类型转换为ArrayList<Integer>。