1. 介绍
泛型可以理解为用来修饰数据类型(除了基本类型)的参数。比如一个ArrayList对象,在没有使用使用泛型时可以往里面加任意类型的数据,但这样并不安全,所以可以使用泛型来限制,如ArrayList<String>就是只能往这个集合里面加String类型的数据。
2. 自定义泛型
2.1 泛型类
假设已定义了Dog和Cat类,都有一个String类型的name字段,那么泛型类可如下定义
public class Person<T> { // 这是一个泛型类,泛型接口的定义也类似
private String name;
// 宠物的类型不确定,可能是Dog,可能是Cat,于是使用泛型
private T pet;
public T getPet() {
return pet;
}
public void setPet(T pet) {
this.pet = pet;
}
}
public class Test {
public static void main(String[] args) {
Person<Dog> p = new Person<>();
p.setPet(new Dog("路卡利欧"));
System.out.println(p.getPet().getName());
}
}
2.2 泛型方法
在方法中包含泛型结构,且其泛型与类的泛型没有任何关系。
public class MyUtil {
// 这是一个泛型方法,即便它的所属类不是泛型类
// static后面的<E>起到提示作用,告诉编译器E是泛型,而不是某个具体的类
public static <E> List<E> copyFromArrayToList(E[] arr) {
List<E> list = new ArrayList<>();
for (E e : arr) {
list.add(e);
}
return list;
}
}
3. 通配符
定义三个类,Creature类,Person类,Student类。继承关系为:Creature ← Person ← Student
3.1 直接操作List
| add()方法 | get()方法 | |
|---|---|---|
| List<? extends Person> | 只能添加null | 可以用Object,Person及其父类来接 |
| List<? super Person> | 可以添加null,Person及其子类 | 只能用Object来接 |
public class Test {
public static void main(String[] args) {
List<? extends Person> list1 = new ArrayList<>();
// list1.add(new Creature()); 编译不通过
// list1.add(new Person()); 编译不通过
// list1.add(new Student()); 编译不通过
list1.add(null);
Object object = list1.get(0);
Creature creature = list1.get(0);
Person person = list1.get(0);
// Student student = list1.get(0); 编译不通过
List<? super Person> list2 = new ArrayList<>();
// list2.add(new Creature()); 编译不通过
list2.add(new Person());
list2.add(new Student());
list2.add(null);
Object object2 = list2.get(0);
// Creature creature2 = list2.get(0); 编译不通过
// Person person2 = list2.get(0); 编译不通过
// Student student2 = list2.get(0); 编译不通过
}
}
3.2 List作为方法参数
- List<? extends Person> list 作为方法参数时,可以传 List<Person及其子类>
- List<? super Person> list 作为方法参数时,可以传 List<Person及其父类>
public class Test {
public static void main(String[] args) {
List<Creature> creatureList = new ArrayList<>();
List<Person> personList = new ArrayList<>();
List<Student> studentList = new ArrayList<>();
// testExtends(creatureList); 编译不通过
testExtends(personList);
testExtends(studentList);
testSuper(creatureList);
testSuper(personList);
// testSuper(studentList); 编译不通过
}
public static void testExtends(List<? extends Person> list) {
}
public static void testSuper(List<? super Person> list) {
}
}
4. 其他知识点
-
如果类A是类B的父类,那么G<A>和G<B>没有父子关系,如下所示。但A<G>是B<G>的父类。
public class Test { public static void main(String[] args) { List<Object> list1 = null; List<String> list2 = null; // 编译不通过 // list1 = list2; } } -
如果泛型要实现某个接口,要用extends关键字,而不是implements,如下所示
public class MyUtil { public static <E extends Serializable> List<E> copyFromArrayToList(E[] arr) { List<E> list = new ArrayList<>(); for (E e : arr) { list.add(e); } return list; } }