Java泛型(Generics)是JDK5开始引入的一个新特性,允许在定义类和接口的时候使用类型参数(Type Parameter)。声明的类型参数在使用时用具体的类型来替换,现在泛型最主要的应用是在JDK5中的新集合类框架中,Map, List均有用到。其中的优点不言而喻,我们可以横向扩展更多的类,缺点呢,其实也就是他的优点,因为这需要我们在使用泛型类的时候,要很清楚自己的代码目地,不能使用错误的类型。
最基本的泛型类
/**
* 最基本的泛型类,类型由自己定义
* @author dhb
*
* @param <T>
*/
public class Point<T> {
private T var;
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
}public class GenericExample {
public static void main(String[] args) {
Point<String> p = new Point<String>();
p.setVar("coder");
System.out.println(p.getVar());
}
}
多个泛型类型
/**
* 多个泛型类型,一般多个最好是以靠近T的字母,如S,R等
* @author dhb
*
* @param <T>
* @param <S>
*/
public class Notepad<T, S> {
private T key;
private S value;
public T getKey() {
return this.key;
}
public S getValue() {
return this.value;
}
public void setKey(T key) {
this.key = key;
}
public void setValue(S value) {
this.value = value;
}
}public class GenericExample {
public static void main(String[] args) {
Notepad<String, Integer> p = new Notepad<String, Integer> ();
p.setKey("coder");
p.setValue(99999);
System.out.println("key: " + p.getKey());
System.out.println("value: " + p.getValue());
}
}
在方法参数中使用通配符"?"
/**
* 该例子关键在main方法里
* @author dhb
* @param <T>
*/
public class Info<T> {
private T key;
public T getKey() {
return this.key;
}
public void setKey(T key) {
this.key = key;
}
@Override
public String toString() {
return this.key.toString();
}
}public class GenericExample {
public static void main(String[] args) {
Info<String> i = new Info<String>();
i.setKey("coder");
fun(i);
Info<Integer> j = new Info<Integer>();
j.setKey(9999);
fun(j);
}
public static void fun(Info<?> temp) {
System.out.println("Content: " + temp);
}
}
向上转型失败
/**
* 该例子关键在main方法里
* @author dhb
* @param <T>
*/
public class Info<T> {
private T key;
public T getKey() {
return this.key;
}
public void setKey(T key) {
this.key = key;
}
@Override
public String toString() {
return this.key.toString();
}
}public class GenericExample {
public static void main(String[] args) {
Info<String> strEg = new Info<String>();
Info<Object> objEg;
// 编译错误"Type mismatch: cannot convert from Info<String> to Info<Object>"
// 向上转型失败,String -> Object
//objEg = strEg;
}
}
泛型在接口中的使用
interface Info<T> {
public T getVar();
}public class InfoImpl<T> implements Info<T> {
private T var;
public InfoImpl(T var) {
this.setVar(var);
}
public void setVar(T var) {
this.var = var;
}
public T getVar() {
return this.var;
}
}
public class InfoImpl1 implements Info<String> {
private String var;
public InfoImpl1(String var) {
this.setVar(var);
}
public void setVar(String var) {
this.var = var;
}
public String getVar() {
return this.var;
}
}
public class GenericExample {
public static void main(String[] args) {
Info<String> strEg = new InfoImpl<String>("coder");
System.out.println("Content: " + strEg.getVar());
Info<String> strEg1 = new InfoImpl1("coder1");
System.out.println("Content: " + strEg1.getVar());
}
}
通配符和extends, super的使用
/**
* 该例子关键在main方法里
* @author dhb
* @param <T>
*/
public class Info<T> {
private T key;
public T getKey() {
return this.key;
}
public void setKey(T key) {
this.key = key;
}
@Override
public String toString() {
return this.key.toString();
}
}public class GenericExample {
public static void main(String[] args) {
Info<String> strEg = new Info<String>();
strEg.setKey("coder");
Info<Integer> intEg = new Info<Integer>();
intEg.setKey(9999);
// upTypeLimit(i);
// 使用Integer,Number类型均可以
upTypeLimit(intEg);
// 编译报错"The method downTypeLimit(Info<? super String>) in the type
// GenericExample is not applicable for the arguments (Info<Integer>)"
// downTypeLimit(intEg);
// 由于使用的是super,downTypeLimit只能接收String本身和Object
// 查看了String的继承关系,没有继承其他类,只有Object
downTypeLimit(strEg);
Info<Object> objEg = new Info<Object>();
objEg.setKey(9999);
downTypeLimit(objEg);
}
/**
*
* <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类
*
* @param temp
*
*/
public static void upTypeLimit(Info<? extends Number> temp) {
System.out.println("Content: " + temp);
}
/**
*
* <? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object
* 在此例中,表示T只能为Object或String,因为String只继承于Object
*
* @param temp
*
*/
public static void downTypeLimit(Info<? super String> temp) {
System.out.println("Content: " + temp);
}
}
伪泛型
不存在真正的泛型类,泛型类对Java虚拟机来说是透明的.JVM并不知道泛型类的存在,换句话来说,JVM处理泛型类和普通类没什么区别的.因此在静态方法、静态初始化块、静态变量里面不允许使用类型形参。- 以下方式都是错误的
private static T data;
static {
T f;
}
public static void func() {
T name = 1;
}
下面的例子可以从侧面验证不存在泛型类
public static void main(String[] args) {
List<String> a1 = new ArrayList<>();
List<Integer> a2 = new ArrayList<>();
System.out.println(a1.getClass() == a2.getClass());
System.out.println(a1.getClass());
System.out.println(a2.getClass());
}
输出:
true
class java.util.ArrayList
class java.util.ArrayList