2017-06-19 152 views
1

這似乎是一個編譯器問題,或者可能是由於設計而存在的。使用更多的泛型擴展類時,Java類信息會丟失

ClassA是一個有兩種泛型的類。 ClassB將通過提供一種固體泛型來擴展ClassA,但仍然暴露另一種。

在下面的例子中,將傳入E的類型將擴展ClassA,所以當調用任何方法時,如果需要,返回類型仍然是可以調用子類型方法的子類型。這背後的動機是做一個建設者模式,例如,

ClassB b = new ClassB<String>().m1().m2().m3().m4()...... 
public class ClassA<E, T> { 
    public final E e; 
    public final T t; 

    public ClassA(T t) { 
     this.e = (E)this; 
     this.t = t; 
    } 

    public E printA() { 
     System.out.println("AAAAAA"); 
     return e; 
    } 
} 

public class ClassB<T> extends ClassA<ClassB, T> { 
    public ClassB(T t) { 
     super(t); 
    } 

    public ClassB printB() { 
     System.out.println("BBBBBB"); 
     return this; 
    } 

    public static void main(String[] args) { 
     ClassB<String> classB = new ClassB<>("Hello World"); 
     // classB.printA().printA().printA(); // This will fail, after the second printA() return Object type instance instead of ClassB. 
     System.out.println(classB.printA().printA().getClass()); // This will print "class ClassB", so the class information it still there. 
     ((ClassB)classB.printA().printA()).printA(); // Casting the instance to ClassB again will make it work again. 
    } 
} 

的問題是,當你調用該方法兩次,返回實例類型會丟失,所以這將是一個Object類型,而不能調用任何ClassA/B方法沒有鑄造它。這太奇怪了。

有什麼想法?

+0

'class ClassB extends ClassA ,T>' – Zefick

+3

*「這似乎是一個編譯器問題」*。這是不可能的。你應該認爲問題在你身邊。 –

+0

@zefick謝謝。 –

回答

6

您的類ClassB是一個通用的類,但是當您不提供類型參數時,您正在選擇不使用泛型。

而你正在做的是,這裏

public class ClassB<T> extends ClassA<ClassB, T> 
             ^^^^^^ 

這裏

public ClassB printB() 
     ^^^^^^ 

所以只需將這些行更改爲

public class ClassB<T> extends ClassA<ClassB<T>, T> 
              ^^^ 

public ClassB<T> printB() 
      ^^^ 

然後它會工作。

+0

你是對的!謝謝。 –