1. 什么是泛型中的限定通配符和非限定通配符?
限定通配符对类型进行了限制。有两种限定通配符,一种是<? extends T>,它通过确保类型必须是T的子类来设定类型的上界,另一种是<? super T>它通过确保类型必须是T的父类来设定类型的下界。泛型类型必须使用限定内的类型来进行初始化,否则会导致编译错误。另一方面<?>表示非限定通配符,因为<?>可以用任意类型来代替。
2. List , List<Object>,List<String> ,List<?>四种情形的注意点?
- List , List<Object > List<?>通过add 方法,可以添加任一类型的数据!
- List <Object> list1 , List<String> list2 , List list3 , List<?> list4
- list1 = list2 // 错误的不能的
- list3 = list2 可以的
- list4 = list2 可以的
那么 List 与 List<String> 的不同?
参数类型是类型安全的,而且类型安全是由编译器保证的,但原始类型List却不是类型安全的。
使用泛型参数类型你不需要进行类型转换,但是使用原始类型,你需要进行显示的类型转换。
List listOfRawTypes = new ArrayList();
listOfRawTypes.add("abc");
listOfRawTypes.add(123); //编译器允许这样,但是在运行时却会出现异常
String item = (String)listOfRawTypes.get(0); //需要显示的类型转换
item = (String)listOfRawTypes.get(1); //抛出ClassCastException,因为Integer不能被转换为String
List<String> listOfString = new ArrayList();
listOfString.add("abcd");
listOfString.add(123);//编译错误,比在运行时错误要好
item = listOfString.get(0); //不需要显示的类型转换---编译器自动转换
3. 类型擦除?
它只在程序源码中存在,在编译后的字节码文件中,就已经被替换为原来的原生类型(Raw Type,也称为裸类型)了,并且在相应的地方插入了强制转型代码,因此对于运行期的Java语言来说,ArrayList<int>与ArrayList<String>就是同一个类
下面的这个例子,编译是不能够通过的,因为编译的时候,就会把类型擦除,变成了原始类型List<E>!!
public class GenericTypes {
public static void method(List<String> list) {
System.out.println("invoke method(List<String> list)");
}
public static void method(List<Integer> list) {
System.out.println("invoke method(List<Integer> list)");
}
}
4. 数组没有泛型,用ArrayList