所谓“泛型”,就是“宽泛的数据类型”,任意的数据类型。在泛型中,不但数据的值可以通过参数传递,数据的类型也可以通过参数传递。T1, T2 只是数据类型的占位符,运行时会被替换为真正的数据类型。
在引入范型之前,Java类型分为原始类型、复杂类型,其中复杂类型分为数组和类。引入范型后,一个复杂类型就可以在细分成更多的类型。例如原先的类型List,现在在细分成List<Object>, List<String>等更多的类型。注意,现在List<Object>, List<String>是两种不同的类型,他们之间没有继承关系,即使String继承了Object。下面的代码是非法的:List<String> ls = new ArrayList<String>();List<Object> lo = ls; 这样设计的原因在于,根据lo的声明,编译器允许你向集合 lo 中添加任意对象(例如Integer),但是其对象类型是List<Object>,破坏了数据类型的完整性。
泛型类或接口
- className<dataType1, dataType2> var = new className<dataType1, dataType2>();
- 类型参数只能用来表示引用类型,不能用来表示基本类型。
- 因为在使用泛型类时指明了数据类型,赋给其他类型的值会抛出异常,既不需要向下转型,也没有潜在的风险。
泛型方法
- 类型参数需要放在修饰符后面、返回值类型前面。一旦定义了类型参数,就可以在参数列表、方法体和返回值类型中使用了。例如:public <T1, T2> void printPoint(T1 x, T2 y){ }
- 与使用泛型类不同,使用泛型方法时不必指明参数类型,编译器会根据传递的参数自动查找出具体的类型。泛型方法除了定义不同,调用就像普通方法一样。
- 泛型方法与泛型类没有必然的联系,泛型方法有自己的类型参数,在普通类中也可以定义泛型方法。
类型擦除
如果在使用泛型时没有指明数据类型,那么就会擦除泛型类型。因为在使用泛型时没有指明数据类型,为了不出现错误,编译器会将所有数据向上转型为 Object。
通配符
上限通配符(upper boundedwildcard)
<? extends Number> 就代表可以接受Number以及它的子类作为参数。这种声明方式被称为。
通过 extends 关键字可以限制泛型的类型,<T extends Number> 表示 T 只接受 Number 及其子类,传入其他类型的数据会报错。extends 后面可以是类也可以是接口。但这里的 extends 已经不是继承的含义了,应该理解为 T 是继承自 Number 类的类型,或者 T 是实现了 XX 接口的类型。
如果加入多个限定,可以用“&”连接起来,但是由于java是单继承,多个限定中最多只能有一个类,而且必须放在第一个位置。
例如:public class Box<T extends Number & Cloneable & Comparable>{}
下限通配符(lower bounded wildcard)
<? super Integer> 代表可以接受Integer以及它的父类作为参数。
无限定通配符(Unbounded Wildcards)
只有一个?,通常在两种情况下会使用无限定通配符:
(1)如果正在编写一个方法,可以使用Object类中提供的功能来实现
(2)代码实现的功能与类型参数无关,比如List.clear()与List.size()方法,还有经常使用的Class<?>方法,其实现的功能都与类型参数无关。
需要特别注意的是,List<?>与List<Object>并不相同,无论A是什么类型,List<A>是List<?>的子类,但是,List<A>不是List<Object>的子类。
参考:
http://blog.163.com/yanenshun@126/blog/static/12838816920157432855399/
http://blog.csdn.net/jinuxwu/article/details/6771121 |