Java泛型是Java SE5之后才出现的,泛型实现了参数化类型的概念。泛型可用于接口、类和方法。这里有些要注意的点,我等会会一一说到。
泛型类型参数
在定义泛型类型和泛型方法时,常用到泛型类型参数,泛型类型参数是在实例化泛型时指定类型的占位符,泛型类型参数放在“<>”内,多个类型参数用”,”号分隔,如“<E,T>”。
泛型类型参数命名建议:
(1)当泛型类型参数为单个字母时,建议用T表示。
(2)当泛型类型参数用单词定义时,建议在单词前加T。不过,我们一般不用这种格式。
泛型类
泛型类是指在类级别上使用了泛型的类。格式为:
class className<T>
这里,T就是泛型参数,代表某个类,此时,在这个类里可以使用类型占位符T了。
泛型方法
泛型类是指在方法级别上使用了泛型的方法。格式为:
<E>放在方法签名的返回值前面
在这个方法里,就可以使用E这个类型了。使用泛型方法时需要注意:
1. 只有在方法签名返回值前面加了泛型类型参数的方法才是泛型方法,而一个方法仅使用了类的泛型参数类型作为参数的类型或返回值的类型,此时这个方法并不是泛型方法;
2.有了1的基础,如果一个泛型方法的类型参数和类的泛型参数命名成一样了,此时泛型方法的泛型参数并不受类泛型参数的限制,即泛型方法的类型参数和类的泛型参数无关。
3.静态泛型方法不能使用类的泛型参数,所以此时只能将泛型定义在方法级别上。
4.由于泛型方法和泛型类互不影响,所以类是否是泛型类并不影响泛型方法的定义,即不是泛型类也可以有泛型方法。
public class Template<T>{
...
//method1并不是一个泛型方法,因为method1没有自己的参数类型
public T method1(...){...}
//method2是一个泛型方法
public <E>void method2(...){...}
//此时,泛型方法method3的参数类型也是T
//如果是Template<String>,那么这里这个method3的T并不是就是String了,仍然可以是任意某类型
public <T>T method3(...){...}
//staticMethod不是一个合法的声明。因为使用了类的泛型参数类型
//public static void staticMethod(T t,...){...}
//staticMethod2才是合法的,此时即使与类的泛型参数类型取名一致,但是依然独立于类的泛型参数类型
public static <T>void staticMethod2(...){...}
}
泛型接口
泛型类是指在接口级别上使用了泛型的接口。格式为:
public interface<T> interfaceName{...}
在这个接口里,就可以使用T这个类型了。同样的,泛型接口和泛型方法互不影响,所以要是在泛型接口里定义了一个泛型方法,实现类里就必须完整实现这个含泛型参数的泛型方法。使用泛型接口时需要注意:
1. 如果实现类在实现泛型接口时指定了泛型接口的参数类型,那么此时这个实现类显式带不带这个参数类型并不影响什么,同时这个泛型类可以维护自己的类泛型参数;
public interface TemplateInterface<E>{...}
//实现类,此时指定了泛型接口的参数类型
//这里TemplateInterfaceImpl后面加不加<String>没有任何影响
public class TemplateInterfaceImpl implements TemplateInterface<String>{...}
2. 如果实现类在实现泛型接口时没有指定泛型接口的参数类型,那么此时这个实现类必须显式带有这个参数类型,并且可以拓展维护该类自己的类泛型参数类型;
public interface TemplateInterface<E>{...}
//实现类,此时未指定泛型接口的参数类型
//这里TemplateInterfaceImpl后面必须加<E>,同时可以有自己的类泛型参数,比如<E, T>
public class TemplateInterfaceImpl<E,...> implements TemplateInterface<E>{...}
3.泛型接口里含有泛型方法,那么实现类里必须完整实现该方法。
public interface TemplateInterface<E>{
//method1:非泛型方法
E method1(...);
//method2:泛型方法
<E>E method2(...);
}
//实现类:注意method1和method2的区别
public class TemplateInterfaceImpl implements TemplateInterface<String>{
//method1:非泛型方法,此时这里的E全都要用String代替
String method1(...);
//method2:泛型方法,此时,这里的E全都不能被String代替,而应该仍然是E
<E>E method2(...);
}