2017-05-22 20 views
6

Ich versuche zu verstehen, das Verhalten der unteren und oberen Grenze Wildcards.Generics - Verhalten der unteren/oberen Grenze der Wildcard?

Beim Versuch, den folgenden Code zu kompilieren, ist ein Problem aufgetreten.

Collection<? extends Object> c = new ArrayList<Object>(); 
c.add(new Object()); // Compile time error 

Um das Problem herauszufinden, habe ich einfach die untere Grenze Wildcard als auch versucht. Zum Glück oder leider kompiliert Code gut, aber schafft so viele Verwirrung.

Collection<? super Object> c = new ArrayList<Object>(); 
c.add(new Object()); // Compiles fine 

Kann mir jemand erklären, wie diese beiden Code-Schnipsel funktionieren. Es wäre toll, wenn jemand weitere Beispiele/Links zur Verfügung stellen könnte.

Bitte korrigieren Sie mich, wenn ich oben etwas falsch gemacht habe.

Vielen Dank im Voraus.

+0

@JornVernee Stimmen Sie zu, dass es sich um PECS handelt. –

Antwort

6

? bedeutet eine "unbekannte Art".

Collection<? extends Object> repräsentiert eine Sammlung von einer Art von Objekt. Dieser "Typ" kann jeder Typ sein, der eine Unterklasse von Object oder Object selbst ist. Welcher Typ genau? Der Compiler weiß es nicht.

Wenn Sie versuchen, eine neue Object der Sammlung hinzuzufügen, können Sie nicht. Dies liegt daran, dass der Typ der Sammlung nicht bekannt ist. Es kann ein ArrayList<String> sein. Es kann ein sein. So ist der Compiler sagt

„Was ist, wenn die Sammlung ArrayList<String> ist? Sie kein Object dort setzen!“

Grundsätzlich ist der Compiler zu vorsichtig, um Sie das tun zu lassen.


Collection<? super Object> repräsentiert eine Sammlung von einem bestimmten Objekttyp. Dieser "Typ" kann jeder Typ sein, der eine Oberklasse von Object oder Object selbst ist. Es kann nur eine Sache sein - Object, weil Object keine Oberklasse hat. Deshalb können Sie der Sammlung ein neues Object hinzufügen.

Auch wenn Object eine Superklasse hat, können Sie immer noch eine new Object() hinzufügen. Nennen wir die Oberklasse von ObjectMyClass. Jetzt kann die Sammlung entweder eine Sammlung von MyClass oder Object sein. Was auch immer es ist, Sie können eine Object hinzufügen.

+0

Ich habe den Teil über 'Collection 'und es macht Sinn. Aber was ist der Grund dafür, dass * ANTWORT * ANTWORT * 'SupersClass' oder die' Object' Klasse selbst im Falle von 'Collection '? – Yahya

+0

Das ist nur was? Super-Objekt bedeutet. Wenn A B erweitert, können Sie B zu einer Sammlung von A hinzufügen. Das gleiche gilt hier. @ Yahya – Sweeper

+0

@JornVernee oh es ist ein Tippfehler. Ich meine, du kannst A zu einer Sammlung von B hinzufügen. – Sweeper

0

Lassen Sie uns den Klassentyp ändern, um es ein wenig verständlicher zu machen. Ihr erstes Beispiel geändert Number

Collection<? extends Number> c = new ArrayList<Number>(); 

bedeutet, dass es ? Objekte von Typ Number. Es könnte also alles sein, dass extends Number z.B. Integer, Double, Float, BigInteger etc. So können Sie nicht garantieren, welche Art von Number Objekt seit

in der Liste befindet
List<Integer> // only allows Integer 
List<Double> // only allows Double 
List<Float> // only allows Float 

Das ist, warum Sie nichts <? extends Number> hinzufügen können, weil sie entweder eine der Listen über sein könnten .

Der umgekehrte Weg ist für <? super Number>. Das bedeutet, dass jedes Objekt in der Liste ein Vorgänger von Number ist. In diesem Fall dürfen Sie etwas vom Supertyp/Typ Number hinzufügen. Sie garantieren mit ? super Number, dass alles in einem Number ist.

Aber was Sie nicht garantieren können, ist der tatsächliche Typ, z.

list.get(0); // is a Number, but could be a Integer 
list.get(1); // is a Number, but could be a Float 
list.get(2); // is a Number, but could be a Double 

tl; dr extends zum Lesen verwenden und super hinzuzufügen.

Und hier ist eine grafische Darstellung von den docs https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html

enter image description here

Hier eine Erklärung von Jon Skeet ist für <? super Number>

https://stackoverflow.com/a/8083260/4467208

+1

Der Abschnitt über '? Super braucht Arbeit. Du hast das meiste davon rückwärts. 'Integer',' Float' und 'Double' sind nicht möglich, wenn die Grenze'? Superzahl'. –

+0

@JohnKugelman Aber diese Typen sind eine 'Nummer'. Sie müssen nicht unbedingt ein Super-Typ sein. –

+1

'Integer' ist eine Unterklasse von' Number'. '? Super Number' passt * superclasses * (oder 'Number' selbst). Die einzige Oberklasse von 'Number' ist' Object'. –