2015-05-20 14 views
13

Ich habe diesen Code:Java Generics: Mehrere Bounds

public class Test { 

    public static void main(String[] args) { 
     Test t = new Test(); 
     t.callTest(); 
    } 

    public void callTest() { 
     GenericTest gt = new GenericTest<Date>(); // this line don't compile 
     gt.test(new Date()); 
    } 

    class GenericTest<T extends Date & List> { 
     T x; 

     public void test(T y) { 
      System.out.println(x.toString()); 
     } 
    } 
} 

Ich verstehe, warum new GenericTest<Date>() nicht kompilieren, ist es, weil Datum nicht Liste Schnittstelle nicht implementiert, aber wenn ich instanziiert GenericTest gt = new GenericTest() ohne Generika, die gesamte Code funktioniert, und ich verstehe nicht warum. Der Methodentest erwartet (T y) wo T extends Date und implementiert List, aber es funktioniert mit gt.test(new Date()).

Antwort

16

Wenn Sie wie folgt instanziiert:

GenericTest gt = new GenericTest() 

Sie die Rohfassung von GenericTest Typ verwenden. Dies bedeutet, dass der Typ T mit seiner ersten Bindung ersetzt wird (in Ihrem Fall Date). Deshalb hat der Methodenvertrag von GenericTest#test() einen Date Parameter, aber keinen List einen.

Beachten Sie, dass jede Grenze, außer der ersten, eine Schnittstelle sein muss. Nur die erste Grenze kann eine Klasse sein. Der Grund dafür ist, dass es keine Typen geben kann, die von mehr als einer Superklasse erben.

Also, da nur der erste Parameter eine Klasse ist, werden Sie nicht in der Lage sein zu Schalter die Typ-Parameter und die folgende Klassendefinition wird ungültig:

class GenericTest<T extends List & Date> { } 
+0

Sind die Grenzen wirklich wichtig, wenn Sie rohe Typen verwenden? – CKing

+1

Ja, sie spielen eine Rolle. Wenn Sie nur '' (d. H. Type-Parameter ohne Grenzen) haben, wird die Ersetzung "Object" sein. Wenn Sie jedoch '' haben, lautet die Ersetzung "Number". –

+1

Sie haben Recht. Die erste Grenze wird angewendet. Habe es einfach ausprobiert. +1 – CKing

-2

Wenn Sie eine generische erstellen Klasseninstanz ohne generische Parameter gibt der Compiler eine Warnung aus und kontrolliert nicht mehr die Verwendung der erzeugten Instanz. Warum der Code funktioniert, ohne den generischen Typ zu deklarieren - weil in diesem Fall T als Objekt angenommen wird, ist jeder Typ gut

+0

'T wird als Objekt angenommen. Ich glaube, das ist falsch. Siehe die Antwort von @kocko – CKing