六、泛型——5-擦除和转换
5-擦除和转换
(1)在严格的泛型代码中,带泛型声明的类总应该带着类型参数。但也也允许在使用带泛型声明的类时不指定实际的类型参数。如果没有为这个泛型类型指定实际的类型参数,则该类型参数被称作原始类型(raw type),默认是声明该类型参数时指定的第一个上限类型;
(2)当把一个具有泛型信息的对象赋值给一个没有泛型信息的变量时,所有在尖括号之间的类型信息将被扔掉。如一个List<String>类型被转换成List类型,则该List对集合元素的类型检查变成了类型参数的上限(Object):
//上限为Number //原始类型为Number class Apple<T extends Number>{ T size; public Apple(){ } public Apple(T size){ this.size = size; } public T getSize() { return size; } public void setSize(T size) { this.size = size; } } public class Test { public static void main(String[] args) { Apple<Integer> a = new Apple<>(); //a的getSize()方法返回Integer对象 Integer as = a.getSize(); //把a对象赋值给Apple变量,丢失尖括号中的泛型信息 Apple b = a; //b只能知道size的类型是Number Number size1 = b.getSize(); //下面代码将报错 //Integer size2 = b.getSize(); } }
(3)对泛型而言,可以直接把一个List对象赋值给一个List<String>对象,编译器仅仅提示存在未经检查的转换,但如果访问其中的元素,就会引起异常:
import java.util.ArrayList; import java.util.List; public class Test2 { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(6); list.add(8); List list2 = list; //尖括号中的泛型信息被擦除 //下面代码引起 未经检查的转换 警告,在编译、运行时完全正常 List<String> ls = list2; //只要访问ls中的元素,就会引起运行时异常 System.out.println(ls.get(0)); } }