本文总结自: https://www.cnblogs.com/coprince/p/8603492.html
泛型,即"参数化类型",顾名思义,就是讲原本具体的类型参数化,这种参数化的类型可用于类、接口和方法中,称为泛型类、泛型接口和泛型方法
特性: 泛型只在编译阶段有效,编译阶段校验正确后,会将泛型信息擦除,也就是说,泛型信息不会保留到运行时。
根据使用处可分为:泛型类、泛型接口、泛型方法
备注:泛型也能使用多个,用‘,’分隔,例如<T,K>
泛型类
或用于字段,或用于方法
class 类名 <泛型标识>{ private 泛型标识 变量名; }
eg:
public class A <T>{ private T b; }
(个人理解为给类传递参数)
这时实现泛型类,即是:
A<String> a1= new A<String>("aaaaa")
写法很麻烦,也可写作:
A<String> a1= new A<>("aaaaa")
JDK1.8之后声明泛型实例'='后面可以不用写类型
备注: 泛型类型只能是类类型(不能是简单类型,即内置类型,如int、double)
----------------------------------------------------------------------------------------------------------------------------------
泛型接口
public interface A<T>{ public T a(); }
对于实现类
1. 传入标志符号
public class B<T> implements A<T>{ @Override public T bb(); }
这时声明类时,需要将泛型的声明一起放入类中,即类名后加上标志符
2.传入实参
public class B implements A<String>{ @Override public String bb(); }
无需加上实参名
----------------------------------------------------------------------------------------------------------------------------------
泛型方法
首先: 泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型,即参数中要包含泛型!,不要把泛型方法和泛型类里使用泛型的方法弄混。
public <T> T B(A<T> aa){ }
泛型方法最大的标志就是在返回值前标明返回泛型!
----------------------------------------------------------------------------------------------------------------------------------
泛型通配符
通常指的是 '?',
当我们把泛型对象作为方法参数,但又不确定此对象明确类型时,使用它代表确切类型,已达到最佳兼容性
eg:
public void B(A<?> obj){ }
这里?可为String、Interger....
值得注意的是?可理解为所有类的父类,他是类型实参不是形参。
为什么不用T、K代替 '?'
在方法中使用T、K,要么该方法处于泛型类/接口/方法中,要么该方法就是一个泛型方法,而对于寻常方法,只能用 '?'
缩小通配符的代表范围
public void a(Generic<? extends Number> obj){ }
即传入的类型实参必须是指定类型的子类型
特别备注: T extends A 或? extends A 中,如果A是接口,则是实现了此接口,如果A是类,则是继承了此类,extends视情况代表implements或extends!
静态方法中使用泛型
public class A<T> { public static <T> void show(T t){ } }
如果类中的静态方法想要使用泛型,需要将此方法定义为泛型方法,
否则,会报错: "xxx cannot be refrenced from static context"