https://www.cnblogs.com/ooo0/p/7569595.html
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
泛型的好处是在编译的时候检查 类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。
泛型类、泛型接口、泛型方法
public class MyTest {
static class Gen <T> {
private T ob;
public void setOb(T ob) {
this.ob = ob;
}
public T getOb() {
return ob;
}
public void showType () {
System.out.println("T的实际类型:" + ob.getClass().getName());
}
}
public static void main(String[] args) {
Gen<String> gen = new Gen<String>();
gen.setOb("asd");
gen.showType();
Gen<List<String>> listGen = new Gen<>();
listGen.setOb(Arrays.asList("1", "2"));
listGen.showType();
}
}
T的实际类型:java.lang.String
T的实际类型:java.util.Arrays$ArrayList
上面例子中,由于没有限制class Gen<T> 类型持有者T的范围,实际上这里限定类型相当于Object,这和“Object泛型”实质上是一样的。限制比如我们要限制为T为集合接口类型。可以这样做:
class Gen< T extends Collection> 这样类中的泛型T只能是 Collection接口的 实现类,传入 非Collection接口 编译 就会报错。
注意:<T extends Collection > 这里的限定使用关键字 extends,后面可以是类也可以是接口,但这里的 extends 已经不是继承的含义了,应该理解为T类型 实现 Collection接口的类型,或者 T 是继承了 XX类的类型。
public class MyTest {
static class Gen <T extends Collection<?>> {
private T ob;
public void setOb(T ob) {
this.ob = ob;
}
public T getOb() {
return ob;
}
public void showType () {
System.out.println("T的实际类型:" + ob.getClass().getName());
}
}
public static void main(String[] args) {
Gen<List<String>> arrayListGen = new Gen<>();
arrayListGen.setOb(Arrays.asList("213", "asd"));
arrayListGen.showType();
}
}
T的实际类型:java.util.Arrays$ArrayList
虽然Java泛型简单的用extends统一表示了原有的extends和implements概念,但仍要遵循应用的体系,Java只能继承一个类,但可以实现多个接口,所以你的某个类型需要用extends限定,且有多种类型的时候,只能存在一个是类,并且类写在第一位,接口列在后面,也就是:
< T extends SomeClass & interface1 & interface2 & interface3 >
public class Demo < T extends Comparable & Serializable > {
// T 类型 就可以用Comparable 声明的方法和 Serializable 所拥有的特性了。
}
为了解决类型被限制死了,不能动态根据实例来确定的缺点,引入了 “通配符泛型”。针对上面的例子,使用通配泛型格式为< ? extends Collection > ,?代表位置类型,这个类型是实现Collection接口。
注意:
是否拥有泛型方法,与其所在的类是否有泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前。如:
public class MyTest {
public static <T> void hello (T t) {
System.out.println(t.getClass().getName());
}
public static void main(String[] args) {
hello("asd");
hello(123);
hello(new String[]{"3", "2", "1"});
}
}
java.lang.String
java.lang.Integer
[Ljava.lang.String;
使用泛型方法时,不必指明参数类型,编译器会自己找出具体的类型。泛型方法除了定义不同,调用就想普通方法一样。
需要注意,一个static方法,无法访问泛型类的类型参数,所以若要static方法需要使用泛型能力,必须使其成为泛型方法。
https://www.jianshu.com/p/90948ff4a940?utm_source=oschina-app
< ? extends T
> 、逆变 < ? super T >
和不变 T