一、
二、
三、泛型方法
1.
public <T> T test(T t1, T t2){
/*
* T t=t1+t2;
* --错误,因为只有在方法调用时才可以确定T的类型,
* 如果T为引用类型(两个对象,不能相加),则会报错
*/
T t=t2;//--正确,不能进行算数运算,但是可以进行赋值
return t;
}
一、泛型
1.泛型产生的背景:
原因1:集合中保存数据时,编译期间可以保存任何类型的数据,导致取值时转换出错;
原因2:每次取值都需要强制转换,代码冗余繁琐;
2.泛型的定义:
泛型的本质是一个参数化的类型(在程序编码中一些包含参数的类),也就是说所操作的数据类型被指定为一个参数。
参数有两种表现:
表现1:体现在方法的一个参数变量上,定义方法时的参数叫形参,定义方法时传递的参数叫实参;
表现2:体现在类或者方法或者接口上,用泛型的格式展现出来的叫参数类型;
3.泛型的好处:
好处1:泛型对加入的变量激进型安全检查,不符合泛型实际参数的类型编译不能通过;
4.泛型的分类:
4.1.泛型类
(1)定义:
类名<A——Z任何一个字母>{}
泛型类的参数类型可以出现在方法上;
4.2.泛型接口
(1)一个类实现了带泛型的接口时,如果在实现类中具体化泛型(传递了泛型参数);
(2)如果接口的方法中使用了接口中的类型,那么重写该方法中的泛型形参全部要替换为该泛型实参;
(3)接口中泛型也可以在实现类中向实现类传递而不采用泛型实参来替换;
4.3.泛型方法
(1)不能在所有的静态方法、静态初块等所有静态内容中使用泛型的类型参数;
(2)泛型方法的定义和普通方法定义不同的地方在于需要在修饰符和返回类型之间加一个泛型类型参数的声明,表明在这个方法作用域中谁才是泛型类型参数;
(3)class A<T> { ... }中T的作用域就是整个A;
(4)public <T> func(...) { ... }中T的作用域就是方法func;
(5)泛型方法的类型参数可以指定上限,类型上限必须在类型参数声明的地方定义上限,不能在方法参数中定义上限。规定了上限就只能在规定范围内指定类型实参,超出这个范围就会直接编译报错。<T extends X> void func(List<T> list){ ... }
5.泛型通配符
5.1通配符是用“?”代替具体的类型参数。
(1)例如 集合类接口List< ?> 在逻辑上是List、List 等所有List<具体类型实参>的父类;
(2)List < ? extends T> :
①表示该通配符所代表的类型是T类型的子类;
②List中的方法的参数涉及到通配符的都不能被调用,因为编译器不知道集合具体装的是T的哪个子类对象(subclass),所以不可以向集合中添加T的子类对象,包括T对象(因为添加对象要调用add()方法);但是可以向集合中添加T或T的基类对象;
(3)List < ? super T>:
①表示该通配符所代表的类型是T类型的父类;
②可以向集合中添加T或T的子类对象,而不能添加T的某种基类对象(因为添加对象要调用add()方法),也是编译器不知道集合具体装的是T的哪种基类对象(superclass);