在上一篇文章Java学习笔记之泛型(一)泛型类、泛型方法、泛型接口中介绍了泛型的基本用法:泛型类、泛型方法和泛型接口,本文将讨论一下泛型的继承和实现的问题。
父类或者接口中定义的泛型可以被子类或者实现类继承过来吗?答案是肯定的。引深一下,如果父类或者接口中定义了多个泛型,那么子类或者实现类能否继承其中的一部分呢(或者说干脆就不继承了呢)?答案也是肯定的,子类或者实现类想继承几个泛型就继承几个泛型。那么再深入一下,在子类继承了父类的泛型基础上,子类自己能否再定义泛型呢?当然也是可以的。
首先我们定义一个父类,在父类里面定义了两个泛型T1和T2,并在构造方法中打印了其类型:
class Father<T1,T2>{
T1 t1;
T2 t2;
public Father(T1 t1, T2 t2) {
this.t1 = t1;
this.t2 = t2;
System.out.println("t1的类型是: " + t1.getClass());
System.out.println("t2的类型是: " + t2.getClass());
}
}
那么由上面的讨论,可以分为四种情况。
第一种情况:子类继承了父类所有的泛型。
public class Test {
public static void main(String args[]) {
Child1 child1 = new Child1<String, Integer, Float>("hahaha", 1, 1.0f);
}
}
class Father<T1,T2>{
T1 t1;
T2 t2;
public Father(T1 t1, T2 t2) {
this.t1 = t1;
this.t2 = t2;
System.out.println("t1的类型是: " + t1.getClass());
System.out.println("t2的类型是: " + t2.getClass());
}
}
class Child1<T1,T2,T3> extends Father<T1,T2>{
private T3 t3;
public Child1(T1 t1, T2 t2, T3 t3) {
super(t1, t2);
this.t3 = t3;
System.out.println("t3的类型是: " + t3.getClass());
}
}
在上述代码中,子类继承了父类的全部两个泛型T1和T2,除此之外子类还自己创建了一个泛型T3,运行结果如下:
第二种情况:子类只继承父类一部分泛型。
既然是子类继承了父类的一部分泛型,那么父类没被继承的泛型就需要在定义子类的时候将其类型确定了:
public class Test {
public static void main(String args[]) {
//Child1 child1 = new Child1<String, Integer, Float>("hahaha", 1, 1.0f);
Child2 child2 = new Child2<Integer, Float>(1, "haha", 1.0f);
}
}
class Father<T1,T2>{
T1 t1;
T2 t2;
public Father(T1 t1, T2 t2) {
this.t1 = t1;
this.t2 = t2;
System.out.println("t1的类型是: " + t1.getClass());
System.out.println("t2的类型是: " + t2.getClass());
}
}
class Child1<T1,T2,T3> extends Father<T1,T2>{
private T3 t3;
public Child1(T1 t1, T2 t2, T3 t3) {
super(t1, t2);
this.t3 = t3;
System.out.println("t3的类型是: " + t3.getClass());
}
}
class Child2<T1,T3> extends Father<T1,String>{
private T3 t3;
public Child2(T1 t1, String str, T3 t3) {
super(t1, str);
this.t3 = t3;
System.out.println("t3的类型是: " + t3.getClass());
}
}
在上面的代码中我们又新建了一个Child2类,它只继承了父类的一个泛型T1,T3是子类自己定义的一个泛型,父类的第二个泛型我们就要将它随便指定一个类型了。例子里面我们给他指定的是String,代码运行如下:
第三种情况:子类指定父类的所有泛型。
这种情况下子类不继承父类的泛型,那么在定义子类的时候要将父类的所有泛型都指定类型:
public class Test {
public static void main(String args[]) {
//Child1 child1 = new Child1<String, Integer, Float>("hahaha", 1, 1.0f);
//Child2 child2 = new Child2<Integer, Float>(1, "haha", 1.0f);
Child3 child3 = new Child3<Integer>(1, "haha", "xixixi");
}
}
class Father<T1,T2>{
T1 t1;
T2 t2;
public Father(T1 t1, T2 t2) {
this.t1 = t1;
this.t2 = t2;
System.out.println("t1的类型是: " + t1.getClass());
System.out.println("t2的类型是: " + t2.getClass());
}
}
class Child1<T1,T2,T3> extends Father<T1,T2>{
private T3 t3;
public Child1(T1 t1, T2 t2, T3 t3) {
super(t1, t2);
this.t3 = t3;
System.out.println("t3的类型是: " + t3.getClass());
}
}
class Child2<T1,T3> extends Father<T1,String>{
private T3 t3;
public Child2(T1 t1, String str, T3 t3) {
super(t1, str);
this.t3 = t3;
System.out.println("t3的类型是: " + t3.getClass());
}
}
class Child3<T3> extends Father<String, String>{
private T3 t3;
public Child3(T3 t3, String str1, String str2) {
super(str1, str2);
this.t3 = t3;
System.out.println("t3的类型是: " + t3.getClass());
}
}
上面代码中我们新建了一个Child3类,同时指定了父类的泛型都为String,这时候子类只有一个泛型T3了(子类自己定义的泛型而不是继承来的)。
第四种情况:子类不指定父类泛型。
class Child4<T3> extends Father{
private T3 t3;
public Child4(Object obj1, Object obj2, T3 t3) {
super(obj1, obj2);
this.t3 = t3;
System.out.println("t3的类型是: " + t3.getClass());
}
}
这种情况跟第三种情况类似,子类也不从父类继承泛型,不同的是构造方法默认将父类泛型指定为Object,所以在主方法中实例化子类时候传什么参数都是可以的:
Child4 child41 = new Child4<Integer>("haha", "xixixi", 1);
Child4 child42 = new Child4<Integer>(1.0f, 2.0, 1);
Child4 child43 = new Child4<Integer>(1.0f, new Date(), 1);
这时Child4只有一个泛型T3,也就是它自己的泛型。