泛型,Java开发过程中非常重要的类型之一,很大程度上避免了程序在编译时的错误。日常开发中常见的集合、包装类及方法中,都有泛型的身影。
什么是泛型泛型,即参数化类型。
在定义方法时有形式参数,对方法调用时有实际参数。
所谓参数化类型便是将类型由原来具体的类型参数化,类似于方法中的变量参数。此时的类型被定义成了一个参数的形式,称之为类型形式参数,在调用时传入具体的类型。
为什么要使用泛型 泛型可以简化代码,便于多种数据类型执行相同的代码 public int addInt(int a, int b) {
return a + b;
}
public float addFloat(float a, float b) {
return a + b;
}
这里做了 int 及 float 两个不同类型数据的加法,如果还需要 double 类型的加法、long类型的加法等等,那么就需要重新再重载 double 类型的加法、long类型的加法的相关方法。
重载的方法过多,代码冗余,不利于维护。其实这里做的都是同一个功能:加法,泛型可以将执行方法中的形式参数的类型 int、float、、进行参数化,简化代码,从而达到同一方法可供多种数据类型共用的效果。
泛型中的类型在使用时指定,不需要强制类型转换 public static void main(String[] args) {
List list = new ArrayList();
list.add("xiaoMing");
list.add(1);
list.add(1.1);
for (int i = 0; i < list.size(); i++) {
String name = (String) list.get(i);
System.out.println("name = " + name);
}
}
定义了一个集合 list ,在向集合中添加 string 类型元素后,又添加了 int 类型及 float 类型元素,这里是允许的,因为此时集合 list 的默认类型是 object。
在 for 循环中对集合进行输出时
String name = (String) list.get(i);
上面代码中的取值方式出现了 java.lang.ClassCastException 异常。
可以看出,在编码过程中不易发现此类错误,另外,在对集合中的姓名元素取值使用时需要进行强制类型转换。
泛型类泛型是为了参数化类型:在没有或不创建新的类型的情况下,通过泛型指定的不同类型来控制形式参数具体限制的类型。
在泛型的使用过程中,操作的数据类型实际上是被指定为一个参数,在个参数化的类型可以在类、接口及方法中使用,分别称为泛型类、泛型接口及泛型方法。
声明语法用类型变量 T ,并用 <> 括起来,放在类名的后面,用以声明泛型类。
public class Gnericity{ // do something }
类型变量可以是任意的大写字母,常用的有 T、E、K、V等。
使用泛型public class Gnericity泛型类允许有多个类型变量{ private T data; public Gnericity(T data) { this.data = data; } }
类型变量之间用“,”分隔。
public class GnericityMore泛型接口 声明语法{ private K key; private V value; public GnericityMore(K key, V value) { this.key = key; this.value = value; } }
public interface GnericityInterface实现泛型接口 未指定泛型实际参数{ public T getData(); }
public class ImpGnericityimplements GnericityInterface { @Override public T getData() { return null; } }
类在实例化时,需要指定具体类型。
public static void main(String[] args) {
ImpGnericity impGnericity = new ImpGnericity();
}
指定泛型实际参数
public class ImpGnericityMore implements GnericityInterface{ @Override public String getData() { return "string"; } }
实例化时与使用普通类一致。
public static void main(String[] args) {
ImpGnericityMore impGnericityMore = new ImpGnericityMore();
}
泛型方法
是在调用方法的时候指明泛型的具体类型,泛型方法可以在任何的场景中使用,包括普通类和泛型类。
泛型类中的普通方法和泛型方法的区别 普通方法public class Gnericity{ private T data; public Gnericity(T data) { this.data = data; } public T getData(){ return data; } }
getData 方法只是类中的一个普通方法,虽然在方法中使用了泛型,但是其并不是泛型方法。此处的 T 在类创建时已经被声明,当前方法只是将 T 作为一个类型使用。
泛型方法public class Gnericity{ private T data; public Gnericity(T data) { this.data = data; } public T getData() { return data; } public T getDataGnericity(T data) { return data; } }
getDataGnericity 才是一个泛型方法。
在方法的访问修饰符与返回值之间必须要有 < T > 声明,声明后的 T 可以在当前方法的任意位置使用。
在泛型方法中,泛型的数量可以是多个,多个泛型数量之间用“,”分隔。
public限定类型变量V getValue(K key, V value) { return value; }
对类型变量的约束。
现需要使用 compareTo 方法对两个泛型变量进行比较,找出其中的最大值:
publicT maxCompare(T a, T b) { if (a.compareTo(b) > 0) return a; else return b; }
此处是不能使用 compareTo 方法的,应为 T 本身无此方法,如果需要确保 T 有 compareTo 方法,那么必须将 T 限制为实现了 Comparable 的类,如下:
publicT maxCompare(T a, T b) { if (a.compareTo(b) > 0) return a; else return b; }
此处,T 是绑定类型的子类型,Comparable 是 T 的绑定类型,子类型和绑定类型可以是类,也可以是接口。
如果有多个类型变量,且需要对多个类型变量进行约束时, extends 两端允许出现多个:
在限定类型中,至允许出现一个类,且这个类必须是限定列表的第一个。
以上对泛型的限定即可用在泛型方法中,也可以用在泛型类中。
文章同步更新平台 语雀https://www.yuque.com/karenchia
微信公众号


