在实际中,程序时常要与各种数据打交道,合理地组织数据结构以及相应相关操作是程序设计的一个重要方面,比如在程序设计中经常会使用诸如链表、散列表等数据结构。这些数据结构都是可以存放若干个对象的集合,其区别是按照不同的方式来存储对象。为了实现链表这种数据结构,Java在JDK1.2版本之后提供了实现常见数据结构的类,这些类统称Java复合框架。在JDK1.5之后,java开始支持泛型。
Java中的泛型类似于C++中的模板(template),只是类似,其实区别还是比较大的。通过写一个方法而达到一劳永逸的效果。其主要目的是可以建立具有类型安全的集合框架。
1.1. 泛型类声明:
使用 "class 名称<泛型列表>" 声明一个类, 为了和普通的类有所区别,这样声明的类称之为泛型类, 例如:
class Animal <E> 其中 Animal 为泛型类的名称, E 是其中的泛型, 也就是说我们没有指定 E 是属于何种类型的数据, 它可以是任何对象或接口, 但不能是基本数据类型。也可以不用 E 表示泛型,使用一个合理的标示符都可以, 我们一般都取一个大写字母来表示。
比如,设计一个锥, 求其体积:锥只关心其底面积,不关心它的具体形状是什么。
Class Cone <E> {
double height;
E bottom;
public Cone( E b) {
bottom = b;
}
}
1.2. 使用泛型类声明对象:
和普通的类声明对象没太大的差别, 就是多了一对"< >", 而且必须要用具体的类型替换"< >"中的泛型。例如: Cone<Circle > column;
column = new Cone< Circle> (new Circle(point, r));
1.3. 泛型接口:
使用" interface 名称 <泛型列表> "声明一个接口, 这样声明的接口称作泛型接口, 例如:
interface Computer <E>
泛型类和泛型接口都是为了可以建立具有类型安全的数据结构而设计的。它避免了一些强制类型转化时带来的错误。
2:实例分析:
一般的泛型:
package com.jimmy.main; class DemoOne<T> { //T为泛型,一般用大写字母表示 private T value; //定义变量value, 类型由 T 指定, 即:外部指定 public DemoOne(T obj) { //构造函数参数类型有外部指定 this.value = obj; } public void setValue(T value) { //参数类型由外部指定 this.value = value; } public T getValue() { //返回值的类型由外部指定 return this.value; } } public class Generic { public static void main(String args[]) { //构造一个String类型的对象,同时也确定了与此对象相关的操作为String类型; DemoOne<String> one = new DemoOne<String>("hello demo1"); one.setValue(new Integer(1)); //这句出错,传入的参数为Integer对象 one.setValue(new Integer(1).toString()); //这是正确的 System.out.println(one.getValue()); one.setValue("demo1 has changed"); System.out.println(one.getValue()); } }
通配符:
package com.jimmy.main; class DemoTwo<T> { private T value; //定义变量value, 类型由 T 指定, 即:外部指定 public DemoTwo(T obj) { //构造函数参数类型有外部指定 this.value = obj; } public void setValue(T value) { //参数类型由外部指定 this.value = value; } public T getValue() { //返回值的类型由外部指定 return this.value; } } public class Generic { public static void main(String args[]) { //构造一个String类型的对象,同时也确定了与此对象相关的操作为String类型; DemoTwo<String> one = new DemoTwo<String>("hello demo1"); DemoTwo<Integer> two = new DemoTwo<Integer>(new Integer(1)); one.setValue("hello"); two.setValue(new Integer(123)); output(one); output(two); } public static void output(DemoTwo<?> temp) { System.out.println("wildcard charactor: " + temp.getValue()); } }
受限泛型:
package com.jimmy.main; class DemoThr<T> { private T value; //定义变量value, 类型由 T 指定, 即:外部指定 public DemoThr(T obj) { //构造函数参数类型有外部指定 this.value = obj; } public void setValue(T value) { //参数类型由外部指定 this.value = value; } public T getValue() { //返回值的类型由外部指定 return this.value; } } public class Generic { public static void main(String args[]) { //构造一个String类型的对象,同时也确定了与此对象相关的操作为String类型; DemoThr<String> one = new DemoThr<String>("hello demo1"); DemoThr<Integer> two = new DemoThr<Integer>(new Integer(1)); one.setValue("hello"); two.setValue(new Integer(123)); output(one); // output(two); //这句会出错,因为two对象声明的为Integer } public static void output(DemoThr<? extends String> temp) { System.out.println("wildcard charactor: " + temp.getValue()); } }