面试题答案
一键面试-
使用泛型通配符实现方法:
import java.util.List; class Animal {} class Dog extends Animal {} public class Main { public static void processList(List<? extends Animal> list) { // 这里可以读取list中的元素,但不能添加新元素(除了null) for (Animal animal : list) { System.out.println(animal); } } }
在上述代码中,
processList
方法的参数类型是List<? extends Animal>
,这样它既可以接收List<Dog>
(因为Dog
是Animal
的子类),也可以接收List<Animal>
,同时保证了类型安全。 -
<? extends T>
原理及说明:- 原理:
<? extends T>
表示类型的上界,即通配符代表的类型是T
的子类(包括T
本身)。 - 读取和写入:
- 读取:可以从集合中读取元素,因为不管具体是
T
的哪个子类,都可以赋值给T
类型的变量。例如上述代码中,从List<? extends Animal>
中读取元素赋值给Animal
类型变量是安全的。 - 写入:不能向集合中写入除
null
以外的元素。因为编译器只知道集合中的元素是T
的子类,但具体是哪个子类并不明确。如果写入一个具体的T
的子类对象,可能与集合实际存储的子类类型不匹配。例如,假设集合实际是List<Dog>
,如果向List<? extends Animal>
写入一个Cat
(Cat
也是Animal
的子类)对象,就会出现类型错误。
- 读取:可以从集合中读取元素,因为不管具体是
- 原理:
-
<? super T>
原理及说明:- 原理:
<? super T>
表示类型的下界,即通配符代表的类型是T
的超类(包括T
本身)。 - 读取和写入:
- 读取:从集合中读取元素时,由于不知道具体的超类类型,所以只能将读取的元素赋值给
Object
类型(因为Object
是所有类的超类)。例如List<? super Dog>
,读取元素时只能用Object
类型接收。 - 写入:可以向集合中写入
T
类型或T
的子类类型的元素。因为T
及其子类对象肯定可以赋值给T
的超类类型的变量。例如对于List<? super Dog>
,可以向其中写入Dog
对象或者Dog
的子类对象(如Poodle
,假设Poodle
是Dog
的子类)。
- 读取:从集合中读取元素时,由于不知道具体的超类类型,所以只能将读取的元素赋值给
- 原理:
-
区别总结:
<? extends T>
:侧重于读操作,保证从集合中读取的元素可以安全地赋值给T
类型变量,但限制了写操作。<? super T>
:侧重于写操作,保证可以安全地向集合中写入T
及其子类对象,但读操作受限,只能用Object
类型接收读取的元素。