为什么要使用泛型?
- 使用泛型可以使代码看起来更加清晰,规范
- 泛型在编译时期可以检测出不符合泛型对应的类型
- 泛型使我们编程更加简洁,不用强制转换,更加安全
泛型类
public class GenericTest<T> {
T data;
}
在泛型类中的泛型方法
public class GenericTest<T> {
T data;
public <T> T fetch(T t) {
return null;
}
}
需要注意的是,泛型类和泛型方法可以指定不同的类型
GenericTest<Integer> genericTest = new GenericTest<>();
String a = genericTest.fetch("a");
类型擦除
泛型在编译之后,就会有类型擦除
public class GenericTest<T> {
T data;
public GenericTest(T t){
this.data = t;
}
public static void main(String[] args) throws NoSuchFieldException {
GenericTest<Integer> genericTest = new GenericTest<>(1);
Field data = genericTest.getClass().getDeclaredField("data");
System.out.println(data.getType().getName());
}
}
泛型通配符
通配符又被分为限定性通配符和非限定行通配符
- 限定性通配符<? extends 类>
public class GenericTest2<T extends Person> {
T data;
public static void main(String[] args) throws NoSuchFieldException {
GenericTest2<P> test2 = new GenericTest2<>();
Field data = test2.getClass().getDeclaredField("data");
System.out.println(data.getType().getName());
}
}
class Person {
}
class P extends Person{}
类型擦除为Person
- 限定通配符<? super 类>,这种通配符不能再类上声明,可以在方法参数上声明
public class GenericTest3 {
public void test(Collection<? super Dog> t) {
t.add(new Dog());
// 编译错误
t.add(new Animal());
}
}
class Animal {}
class Dog extends Animal{}
- 非限定通配符,不能进行写操作,不能进行类型相关的操作
public void test2(Collection<?> collection) {
// 编译错误
collection.add("a");
}