1 泛型简介
所谓泛型,就是允许在定义类、接口的时候指定类型形参(类型的形式参数的简称),这个类型形参将在声明变量、创建对象时确定,即传入实际的类型参数,也可称为类型实参,这实际上是将数据类型参数化。
Java 5以后增加了泛型,这是从Java程序设计以来变化最大的部分。
2 原理及作用
泛型的本质是参数化类型,泛型提供了编译时类型的安全检测机制,该机制允许程序在编译时检测非法的类型,比如要实现一个能够对字符串(String)、整形(Int)、浮点型(Float)、对象(Object)进行大小比较的方法,就可以使用Java泛型。
在不使用泛型的情况下,我们可以通过引用Object类型来实现参数的任意化,因为在Java中Object类是所有类的父类,但在具体使用时需要进行强制类型转换。强制类型转换要求开发者必须明确知道实际参数的引用类型,不然可能引起前置类型转换错误,在编译期无法识别这种错误,只能在运行期检测这种错误(即只有在程序运行出错时才能发现该错误)。而使用泛型的好处是在编译期就能够检查类型是否安全,同时所有强制性类型转换都是自动和隐式进行的,提高了代码的安全性和重用性。
3 泛型分类和使用
根据泛型使用方式的不同,可以把泛型分为泛型接口、泛型类和泛型方法。它们的定义如下所示:
- 泛型接口:在接口定义的接口名后加上<泛型参数名>,就定义了一个泛型接口,该泛型参数名的作用域存在于接口定义和整个接口主体内。
public interface IGeneral<T> {
public T getId();
}
- 泛型类:在类定义的类名后加上<泛型参数名>,就定义了一个泛型类,该泛型参数名的作用域存在于类定义和整个类主体内。
public class BaseResult<T> {}
- 泛型方法:在方法的返回值之前加上<泛型参数名>,就定义了一个泛型方法,该泛型参数名的作用域包括方法返回值、方法参数、方法异常以及整个方法主体。
public T getData()(T str){
System.out.println(str);
}
4 泛型限制
这里泛型的使用限制有两种含义:其一是什么情况下不能使用泛型,其二是开发者想限制泛型的实例化过程。
以下几种情况泛型是不被允许的。
- 不能使用泛型的形参创建对象。
- 不能在静态环境中使用泛型类的类型参数。
- 异常类不能是泛型的,换句话说,泛型类不能继承java.lang.Throwable类。如类D的定义public class D extends java.lang.Throwable就是不被允许的。
- 泛型不能初始化一个数组,但是可以声明数组。
5 码农来洞见
泛型可使得在编译时执行更严格的类型检查。尤其在集合框架中使用泛型时,它做出了两大贡献。首先,泛型在编译时为集合类型添加了类型检查,以便使集合中保存的对象类型仅限于传递给它的类型。其次,泛型使得从集合中检索元素时不需要进行类型转换。
然而因为泛型是后来添加到 Java 中,而不是从一开始就设计到这种语言中的,所以某些容器无法达到它们应该具备的健壮性。例如,观察一下 Map ,在特定的方法 containsKey(Object key)和 get(Object key) 中就包含这类情况。如果这些类是使用在它们之前就存在的泛型设计的,那么这些方法将会使用参数化类型而不是 Object ,因此也就可以提供这些泛型假设会提供的编译期检查。
因此我们可以得出一个结论:一个广泛使用东西,如果想加入新的成分,它势必会出现一些棘手的问题,因为它在带来便利的同时就会伴随着局限与矛盾。
|