泛型可以解决数据类型的安全问题,其主要方法是在类声明时通过一个标识表示类中的某个属性的类型或者方法返回值及参数的类型。
泛型类的定义格式如下:
[访问权限] class 类名称<泛型类型标识1,泛型类型标识2,...,泛型类型标识n> {
[访问权限] 泛型类型标识 变量名;
[访问权限] 泛型类型标识 方法名() {}
[访问权限] 泛型类型标识 方法名(泛型类型标识 变量名) {}
}
泛型对象定义格式如下:
类名称<具体类> 对象名称 = new 类名称<具体类>();
看上面的格式肯定是比较抽象,现在通过一个示例来使用泛型定义类并且声明对象:
//定义的类如下:
package net.jerryblog.generic;
public class Point<T> {
private T var;
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
}
//使用泛型定义对象并使用
package net.jerryblog.generic;
public class PointDemo {
public static void main(String[] args) {
Point<Integer> pnt = new Point<Integer>();
pnt.setVar(30);
System.out.println(pnt.getVar());
}
}
上面的Point在定义时使用了<T>,T实际上表示此类型是由外部声明本类的对象时指定的。这里使用其他任何字母均可,只不过T是Type的简写,表示类型。这样比较好理解。
上面在new对象时,并没有直接指定成int,而是指定成Integer,这是因为泛型指定是无法指定基本数据类型的,必须指定成一个类。因此涉及基本类型时,就必须指定成其包装类。
如果设置的内容与泛型类型不一致时,编译时就会报错。看看下面的代码:
package net.jerryblog.generic;
public class PointDemo {
public static void main(String[] args) {
Point<Integer> pnt = new Point<Integer>();
pnt.setVar("30");
System.out.println(pnt.getVar());
}
}
上面的代码在使用Point类声明对象时指定类型为Integer,但是实际给Point的成员变量传递值的时候却传递的是String类型,那么在编译期,系统就会报错。而不采用泛型时,编译期间是不会出现错误的,运行期才会抛出ClassCastException异常。
要使用泛型为构造方法指定参数,其实原理也是一样的。
package net.jerryblog.generic;
public class Point<T> {
private T var;
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
public Point(T var) {
this.var = var;
}
}
package net.jerryblog.generic;
public class PointDemo {
public static void main(String[] args) {
Point<Integer> pnt = new Point<Integer>(30);
System.out.println(pnt.getVar());
}
}
如果一个类中有多个属性分别需要使用不同的泛型声明,则可以在定义类的时候使用多个泛型类型。见示例代码:
package net.jerryblog.generic;
public class MultiTypePoint<K,V> {
private K key;
private V value;
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
}
package net.jerryblog.generic;
public class MultiTypeDemo {
public static void main(String[] args) {
MultiTypePoint<Integer,String> pnt = new MultiTypePoint<Integer, String>();
pnt.setKey(1);
pnt.setValue("1");
System.out.println("key:" + pnt.getKey() + " value:" + pnt.getValue());
}
}
如果在定义类时使用了泛型,但是在实用类new对象时没有指定具体类型,在编译时系统会给出警告。但是在运行时,不会有问题。因为系统自动对所有的类型统一采用Object类型进行接收。这样的情况基本等同于下面的代码:
MultiTypePoint<Object,Object> pnt = new MultiTypePoint<Object, Object>();
参考书
《Java开发实战经典》 李兴华 编著