Generics: Was kann zum List-Objekt hinzu?

Steve222

Mitglied
Hallo!

Hier eine Frage aus einem Tutor-System:

Gegeben sei diese Codezeile.
Was kann zu list1 hinzugefügt werden?
Angenommen die class Terra sei eine leere Klasse
und alls notwendigen imports sind gemacht.

Codezeile:
Java:
List <? super Terra> list1 = new ArrayList<Terra>();

Wähle zwei Antworten:

1.) Object can be added
2.) Terra can be added
3.) A sub class of Terra can be added
4.) None of the above
5.) This code will not compile
6.) An Object refering to a Terra can be added


Die richtigen Antworten sind für mich ziemlich merkwürdig.

Wer kann mir erklären, welche es sind und warum sie es sind ?

Gruß
Steve222
 
Zuletzt bearbeitet von einem Moderator:
Hallo,

gehen wir mal die Antworten der Reihe nach durch:

1) Objects
Können nicht hinzugefügt werden, denn Object erbt ja nicht von Terra, es ist umgekehrt.

2) Terra selbst
Kann man hinzufügen, denn das "? super Terra" trifft auf alle Elemente zu, die von Terra erben oder Terra selbst sind.

3) Subklasse von Terra
Siehe 2)

4) Keines
Ist falsch ;)

5) Fehler beim compilen
Syntaktisch ist alles richtig, falls die imports etc. richtig sind.

6) Ein Objekt das auf Terra referenziert
Kann nicht hinzugefügt werden, das Generic bezieht sich auf Klassen bzw. Subklassen selbst.


Falls ich falsch liege, bitte berichtigen meine letzten Erfahrungen mit Generics sind schon etwas länger her ;)

// Edit:
Hier mal der Java-Code zur Überprüfung, meine Antwort sollte richtig sein:
Java:
package de.tutorials.bratkartoffel;

import java.util.ArrayList;
import java.util.List;

public class Test {
	public static Terra b = new Terra();
	
	public static void main(String[] args) {
		new Test();
	}
	
	public Test() {
		List<? super Terra> a = new ArrayList<Terra>();
		
		// 1 --- FEHLER
		a.add(new Object());
		
		// 2 --- OK
		a.add(new Terra());
		
		// 3 --- OK
		a.add(new MyTerra());
		
		// 4
		// --------

		// 5
		// --------
		
		// 6 --- FEHLER
		a.add(this);
	}
}

Gruß
BK
 
Zuletzt bearbeitet:
Hallo BK,

ich denke nicht, dass Deine Antwort zufällig richtig ist, da Du tatsächlich was durcheinander geworfen
hast.
Denn so wie ich es verstanden habe ist
<? super Terra>im Gegensatz zu
<? extends Terra>
verschieden, geradezu gegensätzlich.
Ist es nicht MERKWÜRDIG, dass eine sub-Klasse von Terra hinzugfügt werden kann.
obwohl durch <? super Terra> nur Terra oder Super- , also Oberklassen von Terra gefordert sind?

Gruß
Steve222
 
Hmm,

jetzt wo du es explizit ansprichst... Ich hab da jetzt nichts mehr zu sagen, evtl fällt ja ein Java-Guru über diesen Thread ;)

Gruß
BK
 
Hi.
Denn so wie ich es verstanden habe ist
<? super Terra>im Gegensatz zu
<? extends Terra>
verschieden, geradezu gegensätzlich.
Ist es nicht MERKWÜRDIG, dass eine sub-Klasse von Terra hinzugfügt werden kann.
obwohl durch <? super Terra> nur Terra oder Super- , also Oberklassen von Terra gefordert sind?
Im Grunde sind das zwei verschiedene Paar Schuhe.

Die Beschränkung des Wildcard Typen mit extends bzw. super greift eigentlich nur bei der Zuweisung einer konkreten List<> an eine Wildcard-List.
Java:
List<? super Terra> l = new ArrayList<Z>();
Klappt nur wenn Z == Terra oder eine Oberklasse von Terra ist. Soviel ist klar.

Das hat aber nichts mit den Methodenaufrufen zu tun. Das Problem ist, das man von einer List<? super Terra> trotzdem nicht weiß welcher konkrete Typ tatsächlich in der Liste gespeichert ist.

Java:
class M {}
class N extends M {}
class Terra extends N {}
class Z extends Terra {}

List<? super Terra> l = new Vector<N>(); // OK: N ist Oberklasse von Terra

l.add(new Z()); // OK: in der Liste sind Ns gespeichert, N ist Oberklasse von Terra und deshalb auch von Z
l.add(new M()); // ERROR: M ist zwar Oberklasse von Terra, aber in der Liste sind Ns gespeichert!
  // Ns sind zwar "kompatibel" / zuweisbar an Ms, aber nicht umgekehrt, da N eine Unterklasse von M ist.
Oder nochmal anders ausgedrückt: wenn du weißt das in einer Liste höchstens Elemente der Klasse Terra (oder Oberklassen davon) gespeichert sind, dann könnten in der Liste also Object oder M oder N oder Terra Instanzen drin sein. Logischerweise kann man dann nur Terra bzw. Unterklassen von Terra hinzufügen, weil nur dann in jedem Fall sichergestellt sein kann, dass eine Zuweisung gültig ist.

Gruß
 
Zuletzt bearbeitet:
@deepthroat Richtig

Zum Beispiel geht durch <? super X>
Java:
List<? super Integer> list1 = new ArrayList<Integer>();
        List<Object> list2 = new ArrayList<Object>();
        list1 = list2;
Was sonst nicht gehen würde.

Es sagt sozusagen nur aus, von welchem Typ die Liste ist. D.h. was für konkrete Klassen zugelassen werden.

Diese Notation wird eher bei Methoden verwendet, damit man in der Methodensignatur einen möglichst weiten Rahmen an verschiedenen Listen unterstützt.

Z.B. die Methoden Signatur von Collections.copy:

Java:
public static <T> void copy(List<? super T> dest,
                            List<? extends T> src)

Das wird auch als get/put Principle (Prinzip) beschrieben. Beim Getten muss man ja wissen, dass es genau von dem Typ ist. Wenn du irgendwo etwas addest ist dir das erst einmal egal.
Zum Beispiel kopierst du eine List<Integer> in eine List<Number>.


P.S.: Im O'REILLY Buch "Java Generics and Collections" ist das alles sehr gut erklärt :)
 
Danke für die Tipps zur Arraylist denn wir nehmen diese gerade in der Uni durch. Und ich muss da noch das ein oder andere lesen damit ich es besser verstehe.

Ich hatte dazu einmal auf dieser Seite eine gute Beschreibung zu der Klasse gefunden.
http://www.dpunkt.de/java/Referenz/Das_Paket_java.util/7.html
Und dann finde ich auch hier auf der Seite ist es noch ganz gut beschreiben.
http://www.servervoice.de/java-arraylist-dynamische-arrays/

Wenn ihr noch weitere gute Seiten mit Informationen zur Arraylist habt würde ich mich freuen wenn ihr mir diese nennen könnt.
 
Zurück