一.泛型类
需求: 如果我们需要写一个类,这个类里面有一个成员方法:
1.这个方法在调用的时候可以传入任何类型的对象
2.这个成员方法的返回值是它本身
e.g:
class Person {
public Object test(Object o){
return o;
}
}
那我们在主方法里调用的时候:
Person p=new Person();
Object o1=p.test(“asdasdasd”);
String a1=(String)o1;
System.out.println(a1.charAt(2));
特点:
我们还必须进行向下转型才能使用特殊的方法
但是如果使用泛型类,我们可以这么写:
class Person<T>{
public T test(T o){
}
}
那我们可以这么调用:
Person<String> p=new Person<String>();
String o1=p.test(“asdasdasd”);
System.out.println(o1.charAt(2));
特点:
1.在实例化的过程中指定泛型参数
2.指定完泛型参数后,如果传入其他类型的参数编译就会报错
3.方法在返回的时候不需要我们向下转型
4.如果实例化过程中没有指定泛型参数,则泛型参数相当于 Object
注意: 泛型参数的范围只可以通过 extends 限定泛型参数的一个上界
例如:
class Person<T extends A>{
}
class A{
}
class B extends A{
}
二.泛型类的继承关系
泛型类并不是协变的。意思是说,泛型类的参数具有继承关系,但是泛型类本
身并没有任何关系。
需求:
写一个方法 参数列表 可以接受的参数为 ArrayList,并且对 ArrayList 中的泛型参数有一
定要----例如是 Person+Person 的子类。(Student 类是继承 Person 类的)
错误代码:
void test(ArrayList<Person> o){
}
错误, 因为 ArrayList<Person>和 ArrayList<Student>并没有任何关系。
所以如果要满足上述的需求则可以使用通配符,具体代码如下:
void test(ArrayList<? extends Person> o){
①
}
那如果是要求泛型参数是是某个类+某个类的父类呢?
void test(ArrayList<? super Person> o){
②
}
我们来讨论①②中可以编写的代码:
对于①来说,我们基本上什么--都不能 add,只能 add null。
对于②来说,我们可以 add Person 或者 Person 的子类。
注意: 我们也可以利用 extends 和 super 来确定泛型参数的边界
三.泛型方法
如果我们希望并不是实例化过程告诉我们泛型参数,而是 方法调用过程 传的参数 告
诉我们 返回值得具体类型,从而避免向下转型,则可以使用泛型方法:
原来使用泛型类的参数定义的代码如下:
T test(T t){
}
<E> E test(E t){
}
泛型方法使用场景:
1.静态方法并不能使用类的泛型参数,因为不需要实例化过程
2.如果这个方法比较多变,则尽量使用泛型方法
四.泛型的类型擦除
1.代码演示
2.进阶: 由于数组是协变的,泛型的类型擦除的影响,导致禁止生成具有泛型类类型数组.
Pair<Double> cell=new Pair<>();
cell.setValue(4.5);
Pair<String>[] arr1=new Pairt<>[10];
Object[] arr2=arr1;
arr2[0]=cell;
String s=arr1[0].getValue();
class Pair<T> {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
2566

被折叠的 条评论
为什么被折叠?



