泛型的参数类型可以用在类,接口和方法创建中分别称为:泛型类,泛型接口和泛型方法。
ArrayList<E>:整个称为泛型类型,E表示泛型变量或泛型参数
ArralyList<Integer>:整个称为参数化类型,Integer称为类型参数的实例或者实际类型参数
一、泛型类
泛型继承的四种情况
父类--> abstract class Father<T1,T2>{}
1.全部继承
class Child<T1,T2,T2> extends Father<T1,T2>{}
2.部分继承
calss Child<T1,A,B> extends Father<T1,String>{}
3.实现父类泛型
class Child<A,B> extends Father<Integer,String>{}
子类在继承父类的时候,将父类所有的泛型都实现了,这样子类就不会继承父类的泛型了,即使创建了泛型,也是子类独有的。
4.不实现父类泛型
class Child extends Father{}
忽略父类泛型,既不实现,也不继承;这样不会报错,但是父类所有泛型成员会默认为Object类型
如果子类继承带泛型的父类时,指明了泛型类型,则new子类的时就不需要带<>指明类型了。
如果子类在继承带泛型的父类时,没有指明泛型类型或者部分指明泛型,那么可以沿用泛型。如下
public class Son1<T1,T2> extends Father<T1,T2> {
}
public class Son2<T2> extends Father<Integer,T2> {
}
// 没有类型,被擦除了
public class Son3<T1,T2> extends Father {
}
//保留了父类的,并且自己还添加了新的泛型
public class Son4<T1,T2,A,B> extends Father<T1,T2> {
}
静态方法不能使用类的泛型,异常类不能是泛型的
1.泛型类的定义和使用
class Par<T> {
private T value;
public Pair(T value){
this.value=value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value=value
}
}
======================================
二、.泛型接口跟泛型类一样
三、泛型方法
在方法中出现的泛型结构,泛型参数与类的泛型没有任何关系
泛型方法所属的类是不是泛型没有关系
泛型方法可以声明为静态的
public <E> List<E> copyArrayTOList(E[] arr) {
if(arr == null){
throw new RuntimeException("参数为空");
}
List<E> list = new ArrayList<>();
Arrays.stream(arr)
.forEach(item -> {
list.add(item);
});
return list;
}
public static<T> T get(T t1,T t2){
//此时会编译失败,需要对类型变量T限定类型,不然下面的compareTO会报错
if(t1.compareTo(t2)>=0) {
retrun t1;
}
}
------------------------------------------------------
public static<T extends Comparable> T get(T t1,T t2){
//类型限定在泛型类,泛型接口和泛型方法都可以使用,都用关键字extends,可以&加多个限定
if(t1.compareT(t2)>=0) {
retrun t1;
}
}
1自定义泛型:自定义泛型就是一个数据类型的占位符或者一个数据类型的变量
方法中的泛型类型参数声明非常重要:
2方法上自定义泛型:
修饰<声明自定义泛型>返回值类型 函数名(使用自定义泛型){}
public static <T>T getDate(T t){return t}
与普通方法不一样的得地方是修饰符和返回类型之间需要添加一个泛型类型参数的声明,表明方法作用域中
谁才是泛型类型参数
------------------------------------------------------------
4 通配符的使用:?
类型参数作用域:
class A<T>{}中T的作用于就是整个A
public<T> func(){}中T的作用域就是方法func,
会有作用域覆盖问题
泛型方法类型参数可以指定上限,必须在类型参数声明的地方定义上限,不能再方法参数中定义上限。
<T extends X>void func(List<T>list){}//正确
<T extends X> void fun(T t){}//正确
<T> void func (List<T extends S>){}//编译错误
所有能用类型通配符的地方都可用泛型方法解决问题,并且泛型方法可更好的解决
类型通配符: void func(List<? extends A> list)
完全可以用泛型方法替换:<T extends A> void func(List<T> list
---------------------------------------------------------------------------------
数组类型参数不能是类型变量,除非采用通配符方式
List<?>[] lsa = new List<?>[10];
List<Object> list1 = null
List<String> list2 = null;
List<?> list = null;
list = list1;
list = list2;
补充:对于通配符比如 List<?> 不能向内部添加数据,除了null