在不同的情境下使用的字母意义如下:
E — Element,常用在java Collection里,如:List<E>,Iterator<E>,Set<E>
K,V — Key,Value,代表Map的键值对
N — Number,数字
T — Type,类型,如String,Integer等等
泛型接口定义及使用
- interface Info<T>{ // 在接口上定义泛型
- public T getVar() ; // 定义抽象方法,抽象方法的返回值就是泛型类型
- public void setVar(T x);
- }
(1)、使用方法一:非泛型类
但是在使用的时候,就出现问题了,我们先看看下面这个使用方法:
- class InfoImpl implements Info<String>{ // 定义泛型接口的子类
- private String var ; // 定义属性
- public InfoImpl(String var){ // 通过构造方法设置属性内容
- this.setVar(var) ;
- }
- @Override
- public void setVar(String var){
- this.var = var ;
- }
- @Override
- public String getVar(){
- return this.var ;
- }
- }
(2)、使用方法二:泛型类
- interface Info<T>{ // 在接口上定义泛型
- public T getVar() ; // 定义抽象方法,抽象方法的返回值就是泛型类型
- public void setVar(T var);
- }
- class InfoImpl<T> implements Info<T>{ // 定义泛型接口的子类
- private T var ; // 定义属性
- public InfoImpl(T var){ // 通过构造方法设置属性内容
- this.setVar(var) ;
- }
- public void setVar(T var){
- this.var = var ;
- }
- public T getVar(){
- return this.var ;
- }
- }
- public class GenericsDemo24{
- public static void main(String arsg[]){
- InfoImpl<String> i = new InfoImpl<String>(“harvic”);
- System.out.println(i.getVar()) ;
- }
- };
使用泛型类来继承泛型接口的作用就是让用户来定义接口所使用的变量类型,而不是像方法一那样,在类中写死。
那我们稍微加深点难度,构造一个多个泛型变量的类,并继承自Info接口:
- class InfoImpl<T,K,U> implements Info<U>{ // 定义泛型接口的子类
- private U var ;
- private T x;
- private K y;
- public InfoImpl(U var){ // 通过构造方法设置属性内容
- this.setVar(var) ;
- }
- public void setVar(U var){
- this.var = var ;
- }
- public U getVar(){
- return this.var ;
- }
- }
- StaticFans.StaticMethod(“adfdsa”);//使用方法一
- StaticFans.<String>StaticMethod(“adfdsa”);//使用方法二
从结果中我们可以看到,这两种方法的结果是完全一样的,但他们还有些区别的,区别如下:
方法一,可以像普通方法一样,直接传值,任何值都可以(但必须是派生自Object类的类型,比如String,Integer等),函数会在内部根据传进去的参数来识别当前T的类别。但尽量不要使用这种隐式的传递方式,代码不利于阅读和维护。因为从外观根本看不出来你调用的是一个泛型函数。
方法二,与方法一不同的地方在于,在调用方法前加了一个<String>来指定传给<T>的值,如果加了这个<String>来指定参数的值的话,那StaticMethod()函数里所有用到的T类型也就是强制指定了是String类型。这是我们建议使用的方式。
进阶:返回值中存在泛型
上面我们的函数中,返回值都是void,但现实中不可能都是void,有时,我们需要将泛型变量返回,比如下面这个函数:
- public static <T> List<T> parseArray(String response,Class<T> object){
- List<T> modelList = JSON.parseArray(response, object);
- return modelList;
- }
函数返回值是List<T>类型。至于传入参数Class<T> object的意义,我们下面会讲。这里也就是想通过这个例子来告诉大家,泛型变量其实跟String,Integer,Double等等的类的使用上没有任何区别,T只是一个符号,可以代表String,Integer,Double……这些类的符号,在泛型函数使用时,直接把T看到String,Integer,Double……中的任一个来写代码就可以了。唯一不同的是,要在函数定义的中在返回值前加上<T>标识泛型;
5、其它用法:Class<T>类传递及泛型数组
(1)、使用Class<T>传递泛型类Class对象
List<SuccessModel> modelList = JSON.parseArray(response, SuccessModel.class);
我们把下面这句组装成一个泛型函数要怎么来做呢?
- public static <T> List<T> parseArray(String response,Class<T> object){
- List<T> modelList = JSON.parseArray(response, object);
- return modelList;
- }
通过Class<T>来加载泛型的Class对象
(2)、定义泛型数组
- public static <T> T[] fun1(T…arg){ // 接收可变参数
- return arg ; // 返回泛型数组
- }
- public static void main(String args[]){
- Integer i[] = fun1(1,2,3,4,5,6) ;
- Integer[] result = fun1(i) ;
- }