一、概述
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。
二、泛型的规则限制
1、具体例子
package com.wsheng.aggregator.generic;
/**
* @author Josh Wang(Sheng)
*
* @email josh_wang23@hotmail.com
*
*/
public class Gen<T> {
// 定义泛型成员变量
private T t;
public Gen(T t) {
this.t = t;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public void showType() {
System.out.println("T的实际类型是: " + t.getClass().getName());
}
public static void main(String[] args) {
// 定义一个泛型类Gen的一个Integer的版本
Gen<Integer> intObj = new Gen<Integer>(0);
intObj.showType();
int i = intObj.getT();
System.out.println(" value = " + i);
System.out.println(" ====================== ");
//定义泛型类Gen的一个String的版本
Gen<String>strObj = new Gen<String>("Hello Gen!");
strObj.showType();
String s = strObj.getT();
System.out.println(" value = " + s);
}
}
package com.wsheng.aggregator.generic;
/**
* @author Josh Wang(Sheng)
*
* @email josh_wang23@hotmail.com
*
*/
public class Gen2 {
// 定义一个通用类型成员
private Object obj;
public Gen2(Object obj) {
this.obj = obj;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
public void showType() {
System.out.println("T的实际类型是: " + obj.getClass().getName());
}
public static void main(String[] args) {
// 定义类Gen2的一个Integer版本
Gen2 intObj = new Gen2(2);
intObj.showType();
int i = (Integer) intObj.getObj();
System.out.println(" value = " + i);
System.out.println(" ====================== ");
// 定义类Gen2的一个String版本
Gen2 strOb = new Gen2("Hello Gen!");
strOb.showType();
String s = (String) strOb.getObj();
System.out.println(" value= " + s);
}
}
运行结果:两个例子的运行结果都是一模一样的
2、深入泛型
package com.wsheng.aggregator.generic;
/**
* @author Josh Wang(Sheng)
*
* @email josh_wang23@hotmail.com
*
*/
public class StringFoo {
private String x;
public StringFoo(String x) {
this.x = x;
}
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
}
package com.wsheng.aggregator.generic;
/**
* @author Josh Wang(Sheng)
*
* @email josh_wang23@hotmail.com
*
*/
public class DoubleFoo {
private Double foo;
public Double getFoo() {
return foo;
}
public void setFoo(Double foo) {
this.foo = foo;
}
}
重构
package com.wsheng.aggregator.generic;
/**
* @author Josh Wang(Sheng)
*
* @email josh_wang23@hotmail.com
*
*/
public class ObjectFoo {
private Object x;
public ObjectFoo(Object x) {
this.x = x;
}
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
public static void main(String[] args) {
ObjectFoo strFoo = new ObjectFoo(new StringFoo("Hello Generics!"));
ObjectFoo doubleFoo = new ObjectFoo(new DoubleFoo(0d));
ObjectFoo objectFoo = new ObjectFoo(new Object());
System.out.println("strFoo.getX=" + (StringFoo) strFoo.getX());
System.out.println("douFoo.getX=" + (DoubleFoo) doubleFoo.getX());
System.out.println("objFoo.getX=" + objectFoo.getX());
}
}
运行结果如下:
strFoo.getX=com.wsheng.aggregator.generic.StringFoo@5c3f1224
douFoo.getX=com.wsheng.aggregator.generic.DoubleFoo@30c028cc
objFoo.getX=java.lang.Object@17b68215
解说:在Java 5之前,为了让类有通用性,往往将参数类型、返回类型设置为Object类型,当获取这些返回类型来使用时候,必须将其“强制”转换为原有的类型或者接口,然后才可以调用对象上的方法。
泛型类型实现
package com.wsheng.aggregator.generic;
/**
* @author Josh Wang(Sheng)
*
* @email josh_wang23@hotmail.com
*
*/
public class ObjectFoo {
private Object x;
public ObjectFoo(Object x) {
this.x = x;
}
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
public static void main(String[] args) {
ObjectFoo strFoo = new ObjectFoo(new StringFoo("Hello Generics!"));
ObjectFoo doubleFoo = new ObjectFoo(new DoubleFoo(0d));
ObjectFoo objectFoo = new ObjectFoo(new Object());
System.out.println("strFoo.getX=" + (StringFoo) strFoo.getX());
System.out.println("douFoo.getX=" + (DoubleFoo) doubleFoo.getX());
System.out.println("objFoo.getX=" + objectFoo.getX());
}
}
运行结果:
泛型类语法:
3、高级应用
限制泛型
package com.wsheng.aggregator.generic;
import java.util.Collection;
/**
* @author Josh Wang(Sheng)
*
* @email josh_wang23@hotmail.com
*
*/
public class CollectionGenFoo<T extends Collection<?>> {
private T x;
public CollectionGenFoo(T x) {
this.x = x;
}
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
}
具体的实例化:
public static void main(String[] args) {
/*CollectionGenFoo<ArrayList<String>> listFoo = null;
listFoo = new CollectionGenFoo<ArrayList<String>>(new ArrayList<String>());*/
CollectionGenFoo<Collection<String>> listFoo = new CollectionGenFoo<Collection<String>>(new ArrayList<String>());
System.out.println("实例化成功!" + listFoo);
}
多接口限制
虽然Java泛型简单的用 extends 统一的表示了原有的 extends 和 implements 的概念,但仍要遵循应用的体系,Java 只能继承一个类,但可以实现多个接口,所以你的某个类型需要用 extends 限定,且有多种类型的时候,只能存在一个是类,并且类写在第一位,接口列在后面,也就是:
(泛型方法的类型限定) <T extends SomeClass & interface1 & interface2 & interface3>
(泛型类中类型参数的限制)
public class Demo<T extends Comparable & Serializable> {
// T类型就可以用Comparable声明的方法和Seriablizable所拥有的特性了
}
通配符泛型
为了解决类型被限制死了不能动态根据实例来确定的缺点,引入了“通配符泛型”,针对上面的例子,使用通配泛型格式为<? extends Collection>,“?”代表未知类型,这个类型是实现Collection接口。
4、泛型方法
是否拥有泛型方法,与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前。如:
package com.wsheng.aggregator.generic;
/**
* @author Josh Wang(Sheng)
*
* @email josh_wang23@hotmail.com
*
*/
public class GenericMethod {
public <T> void print(T x) {
System.out.println(x.getClass().getName());
}
public static void main(String[] args) {
GenericMethod method = new GenericMethod();
method.print(" ");
method.print(10);
method.print('a');
method.print(method);
}
}
运行结果:
java.lang.String
java.lang.Integer
java.lang.Character
com.wsheng.aggregator.generic.GenericMethod