2013-04-03 16 views
11

Warum funktioniert 1 und 2 nicht?Java Wildcards vs Typ Parameter

1:

public List<? extends Integer> l1; 
public List<? extends Number> l2 = l1; 

2:

public List<U> l1; 
public List<S> l2 = l1; 
//where U and S have been previously defined as: **S extends Number,U extends Integer** 
+4

Können Sie zeigen, wie Sie sie zuvor für Ihr zweites Beispiel definieren? – Quetzalcoatl

+0

@SaurabhAgarwal ist das nicht der Punkt? Warum funktioniert "irgendeine Unterklasse", aber eine _spezielle_ Unterklasse nicht? – Alnitak

+0

public class WildcardsTest {/ * Code oben in 2 dargestellt * /} – Razvan

Antwort

-2

Da in 1 Sie jede Unterklasse der Integer und Anzahl beziehungsweise sagen.

Aber in der zweiten sagen Sie Generic von U und S und wie diese Generika nicht unterstützt kann Super Sub-Objekt-Konzept der Java-OOP's beziehen.

+0

Sie können es nicht akzeptieren, aber es ist der eigentliche Grund hinter Generika .. !! –

-1

Schauen Sie in 1.1 Sie sagen, jede Klasse, die Integer und in 1.2 jede Klasse erweitert, die Nummer erweitert. Nun ist so eine Integer-Unterklasse der Nummer, deshalb gab es im ersten Fall keinen Fehler. Aber ist 2.1 Sie nur U sagen und in 2.2 nur S und Sie tun

public List<S> l2 = l1 

und l1 vom Typ U nicht S und Generika tun unterstützt nicht eine solche Aufgabe Referenzierung von seiner eigenen. Sie müssen Joker wie im ersten Fall verwenden.

public List<? extends Number> l2 = l1; 

Ihr Problem lösen ..

1

BTW: Sie nicht Integer erweitern können, Integer ist eine final Klasse.

// l1 holds any subclass of Integer and, because Integer implements Number it is also a subclass of Number 
public List<? extends Integer> l1; 
// l1 (see above) implements Number so this is fine. 
public List<? extends Number> l2 = l1; 

// Using Integer here instead of your U because you cannot extend Integer - it is final. 
public List<Integer> l3; 
// Make S extend Number 
static class S extends Number { 
    // Implementing the abstract methods of Number 
} 
// NOT valid because l4 must be a List of S not a list of ANY Number and l3 is a List<Integer> - no connection other than a commmon interface. 
public List<S> l4 = l3; 
+0

Ihre Sprache ist ein wenig verwirrend - ich glaube, Sie haben an einigen Stellen "Unterklasse" gemeint? –

+0

@PaulBellora - Danke - behoben. – OldCurmudgeon

3

Generics are not covariant. Zum Beispiel:

List<Integer> l1; 
List<Number> l2; 
l1 = l2; // incompatible types 
l2 = l1; // also incompatible 

Allerdings bieten wildcarded Arten eine Art und Weise Kovarianz auszudrücken:

List<? extends Integer> l1; 
List<? extends Number> l2 = l1; //legal 

l1 als List von einige unbekannte Art ausgedrückt werden, die oder Integer erstreckt ist. Ähnlich ist l2 ein List eines Typs, der Number ist oder sich erstreckt. Da IntegerNumber erweitert, weiß der Compiler, l1 zu l2 zuweisen muss in Ordnung sein.

Diese Situation ist anders:

<S extends Number, U extends Integer> void someMethod() { 

    List<U> l1; 
    List<S> l2 = l1; //incompatible types 
} 

S und U Typ Parameter sind, dh sie einige spezifische Art Argumente von Anrufern von someMethod (oder Typ Schlußfolgerungs) vorgesehen sind. Diese Typargumente könnten ein konkreter Typ wie Integer oder ein Wildcard-Capture sein.

Während sie auch begrenzt sind, unterscheidet sich dies von der Verwendung von begrenzten Wildcards wie oben. Typparameter sind bei der Deklaration begrenzt - innerhalb des Methodenkörpers verstehen sie sich nicht zu ändern.Zum Beispiel, sagen wir mal, beide S und U-Integer aufgelöst wurden durch den Aufruf:

this.<Integer, Integer>someMethod(); 

In diesem Fall können wir uns vorstellen, das Verfahren Körper wie folgt aussieht:

List<Integer> l1; 
List<Integer> l2 = l1; // okay why not? 

Diese Rechts sein würde, aber wir gerade passiert, um Glück zu haben. Es gibt viele Situationen, in denen es nicht wäre. Zum Beispiel:

this.<Double, Integer>someMethod(); 

Jetzt neu erfinden wir die Methode Körper:

List<Integer> l1; 
List<Double> l2 = l1; // danger! 

So können Sie sehen, dass ein beschränkter Typ-Parameter ein etwas viel anders aus einem beschränkten Platzhalter ist, die unterschiedlichen generische Typen erlaubt zu sein covariantly "getauscht":

List<Integer> l1; 
List<Double> l2; 
List<? extends Number> l3; 
l3 = l1; 
l3 = l2;