泛型概述
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在
类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法
泛型的作用
1、在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。
2、避免了强制转换类型,因为强制类型转换很麻烦,我还要事先知道各个Object具体类型是什么,才能做出正确转换。否则,要
是转换的类型不对,比如将“Hello Generics!”字符串强制转换为Double,那么编译的时候不会报错,可是运行的时候就挂了。
那有没有不强制转换的办法
规则限制
1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
3、泛型的类型参数可以有多个。
4、泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上称为“有界类型”。
5、泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName("java.lang.String");
泛型限制
关键字extends:
如<T extends Collection> Collection可以是类也可以是接口,但这里的extends已经不是继承的含义了,应该理
解为T类型是实现Collection接口的类型,或者T是继承了XX类的类型。
多接口限制
泛型简单的用 extends 统一的表示了原有的 extends 和 implements 的概念,但还是需要遵守系统的体制;继承只能
一个 ,接口可以实现多个。如:<T extends SomeClass & interface1 & interface2 & interface3> 这就是继
承了一个类型和实现了三个接口。
注意:extends后面首先是一个类再是接口
通配符泛型
为了解决类型被限制死了不能动态根据实例来确定的缺点,引入了“通配符泛型”,针对上面的例子,使用通配泛型格式为<?
extends Collection>,“?”代表未知类型,这个类型是实现Collection接口。其中<T> T没有任何限制,实际上相当
于Object类型,T仅仅是个名字,这个名字可以自行定义。
注意:
1、如果只指定了<?>,而没有extends,则默认是允许Object及其下的任何Java类了。也就是任意类。
2、通配符泛型不单可以向上限制,如<? extends Collection>,还可以向下限制,如<? super Double>,表示类型只
能接受Double及其上层父类类型,如Number、Object类型的实例。
3、泛型类定义可以有多个泛型参数,中间用逗号隔开,还可以定义泛型接口,泛型方法。这些都与泛型类中泛型的使用规则
类似。
泛型方法
是否拥有泛型方法,与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前。如:
public class ExampleA {
public <T> void f(T x) {
System.out.println(x.getClass().getName());
}
public static void main(String[] args) {
ExampleA ea = new ExampleA();
ea.f(" ");
ea.f(10);
ea.f('a');
ea.f(ea);
}
}
结果类型:
java.lang.String
java.lang.Integer
java.lang.Character
ExampleA
使用泛型方法时,不必指明参数类型,编译器会自己找出具体的类型。泛型方法除了定义不同,调用就像普通方法一样。
需要注意,一个static方法,无法访问泛型类的类型参数,所以,若要static方法需要使用泛型能力,必须使其成为泛型方法。