Erklähre den Unterschied zwischen super und extends.
| Antwort/ answer | |
|---|---|
Welche dieser Code-Zeilen compiliert einwandfrei?:
List a = new ArrayList();
List<?> b = new ArrayList<String>();
List<String> c = new ArrayList();
List<String> d = new ArrayList<String>();
List<String> e = new ArrayList<?>();
List f = new ArrayList<String>();
| Antwort/ answer | |
|---|---|
Es kann auch die Wildcard ? mit T ersetzt werden, hier ein letztes Beispiel einer Klassendefinition (zumindest fürs erste
):
class generic_Types <T extends Angestellter>{ .. }
Genau wie bei der Wildcard können in diesem Zusammenhang nur Objekte vom Typ Angestellter oder dessen abgeleiteter Klassen aufgenommen werden.
generic_Types <Angestellter> a_generic= new generic_Types <Angestellter> ();
generic_Types <Buchhalter> b_generic = new generic_Types <Buchhalter> ();
können daher problemlos angelegt werden,
generic_Types <Integer> c_generic = new generic_Types <Integer>();
gibt einen CompilerFehler, da falscher Objekt-Typ
alles was an eine andere Methode übergeben werden kann; kann auch direkt zugewiesen werden:
Deswegen hier nur die genannten Beispiele in der Zusammenfassung:
List <Angestellter> a = new ArrayList <Angestellter>();
List <Angestestellter> b= new ArrayList <Buchhalter>();
List <? extends Angestellter> c = new ArrayList <Angestellter>();
List <? super Buchhalter> d = new ArrayList <Angestellter>();
List <?> e = new ArrayList <Angestellter>();
List <Object> f = new ArrayList <Angestellter>(); // Type mismatach
List <Object> g = new ArrayList <Object>();
List <? extends Angestellter> h = new ArrayList <Buchhalter>();
List <? extends Angestellter> i = new ArrayList <? super Buchhalter>(); // Type mismatch
List <? super Angestellter>j= new ArrayList <Buchhalter>(); // Type mismatch
Es gelten zusätzlich die gleichen Regeln für das Hinzufügen von Objekten.
Heute wollen wir uns mal die Übergabe von List ohne jegliche Einschränkungen anschauen:
public static void checkStatus_list (List <?> a){ … }
oder
public static void checkStatus_list (List<Object> a){ … }
Auf den ersten Blick sieht es aus, als wären beide Methoden gleich, aber es gibt Unterschiede:
Bei der Übernahme von <?> ist die Funktion add(Object) ausgeschaltet; ein CompilerFehler wird ausgeben. Hintergrund ist einfach, dass Probleme bei verschiedenen Objekttypen, bzw. deren späterer Weiterbehandlung vermieden werden soll.
Bei der Übernahme von (List<Object> a) kann auch nur der Typ List <Object> übergeben werden, und keine Subklassen. Somit ist für unser Beispiel (List mit Objekten vom Typ Buchhalter, Verkäufer und Angestellter) diese Methode nicht brauchbar.
So, heute die nächste Art von Wildcards:
public static void checkStatus_list (List <? super Buchhalter> a){ … }
Dies bedeutet, dass alle Elemente vom Typ Buchhalter oder deren Oberklassen übergeben werden können.
Auch hier ist ein Cast notwendig, um durch die Elemente zu gehen und die jeweiligen Methoden aufzurufen:
for (Object x : a)
System.out.println(((Angestellter)x).getName());
Hier ist aber Vorsicht geboten; es muss zur Oberklasse gecasted werden, da ansonsten einen Laufzeitfehler (keinen CompilerFehler) auftritt.
Das direkte hinzufügen funktioniert in unserem Beispiel nur beim Typ Buchhalter:
a.add(new Buchhalter());
Es können zwar alle möglichen Elemente vom Typ Buchhalter oder deren Oberklassen übergeben werden, eingefügt werden kann aber nur der aktuelle Typ, da ein heruntercasten nie möglich ist.