参数化的类型:将需要传入的属性,进行参数化,实际调用时才指定传入的数据类型。
逻辑相同
,只是传入的参数不同
,如果不使用泛型就需要进行很多方法的重写
。实现传入不同的参数,来执行相同的代码。
严格要求传入的参数类型,不需要强制类型转换,编译期间就可以发现错误。
定义泛型类:只需在类名后面加尖括号
即可,尖括号中的字母可随意设置
。
public class Demo<T>{
private T data;
public T getData(){
return data;
}
public void setData(T data){
this.data = data;
}
}
public static void main(String[]args){
Demo<String>demo = new Demo<>();
demo.setData("test");
}
定义泛型方法:修饰符
和返回值类型
中间要有<参数类型>
,泛型方法可定义在任意位置。
注意 定义在泛型类中的泛型方法,传入的参数类型可以与泛型类传入的类型不同,泛型类传入的类型只影响普通方法。
public <T> T demo(T t){
return t;
}
调用的两种方式:
1.<String>demo("a");
2.demo("a");
定义泛型接口:与泛型类类似只需在方法名后面加尖括号
即可,尖括号中的字母可随意设置
。
public interface Demo<T>{
public T demo();
}
泛型接口的两种实现方式: 第一种
public class ImpDemo<T>implements Demo<T>{
@Override
public T demo(){
return null;
}
}
第二种
public class ImpDemo<T>implements Demo<String>{
@Override
public String demo(){
return null;
}
}
注意T extends 可继承一个类和多个接口通过&来间隔,但只能继承一个类,并且需写在第一个。
因为java语法规定单继承多实现且必须类放在第一个。
泛型类和方法通用。
public static <T extends Comparable>T min(T a, T b){
if(a.compareTo(b)>0){
return a;
}else{
return b;
}
}
因为static关键字是在实例化之前进行处理的,所以编译器不能确定要生成何种类型
静态方法本身是泛型方法可以public class Demo<T>{
private T data;
public Demo{
//①
this.data = new T();
}
}
③泛型不支持
基本数据类型但支持
他们的包装类因为泛型需要对象类型
④不支持类型判定即不支持instanceof
,因为编译时会对泛型进行擦除。
⑤可以定义泛型数组,但不能创建泛型数组。
⑥泛型类不能继承异常e xtend Exception,也不能捕获泛型异常
有一种写法可以
public <T extend Throwable> void doSomeThing(T t) throws T{
try{}catch(Throwable e){
throw t;
}
}
泛型没有任何继承关系
但泛型类可以继承或扩展其他泛型类,如List和ArrayList
<? extend 类>
?代表子类
或类本身
。
注意只能使用在方法上不能在类上用
,且类代表了上界
,即?不能传入类的父类
。
不支持set且只能get上界本身
用于安全的访问
数据
②定义通配符:<? super 类>
?代表类
或类的父类
。
注意只能使用在方法上不能在类上用
,且类代表了下界
,即?不能传入类的子类
。
支持set类本身和类的子类,不能set类的父类
用于安全的写入
数据类型擦除,变成了Object,如果泛型有extends 则取extends的第一个用来作为擦除类型,伪泛型jdk编译时会自动做类型转换。
最后送一句话给自己也与各位共勉
行百里者半九十,不要轻易自满,永远记得坚持超越自己,加油!!!