Generics und Vererbung.

Status
Nicht offen für weitere Antworten.
G

Guest

Gast
Hallo,

kann mir bitte jemand erklären, warum der folgende Code nicht geht?
Code:
List<? extends Number> list = new ArrayList<? extends Number>();
list.add(1);
list.add(2.5d);
Soll eine Collection sein, die alle möglichen Typen von Zahlen akzeptiert
bzw. alles, was von Number abgeleitet ist (Integer, Double ...)

Ein anderes Beispiel (Basismodel + eine Erweiterung)
Code:
class A {
  private int a;
    
  public A(int a) {
    setA(a);
  }

  public int getA() {
    return a;
  }

  public void setA(int a) {
    this.a = a;
  }    
}
  
class B extends A {
  private int b;
    
  public B(int a, int b) {
    super(a);
    setB(b);
  }
    
  public int getB() {
    return b;
  }
    
  public void setB(int b) {
    this.b = b;
  }
}

...
List<? extends A> list = new ArrayList<? extends A>();
list.add(new B(1,1));
list.add(new B(1,2));
Die Fehlermeldung lautet
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
Cannot instantiate the type ArrayList<? extends A>
Bound mismatch: The method add(? extends A) of type List<? extends A> is not applicable for the arguments (B). The wildcard parameter ? extends A has no lower bound, and may actually be more restrictive than argument B


Irgendeine Idee?
 
S

stev.glasow

Gast
Schreib einfach
List<Number> list = new ArrayList<Number>();
bzw.
List<A> list = new ArrayList<A>();
 
B

Beni

Gast
Mit "List<? extends Number> list" sagst du, dass list jede Liste mit irgendwelchen Beschränkungen die auch Number sind, sein kann. Z.b. Vector<Double>, ArrayList<Integer>...
Das man aber einer ArrayList<Integer> keinen Double zuweisen kann, ist klar. Und weil das in deinem Code potentiell möglich ist, gibts ein Fehler.

"new ArrayList<? extends Number>();" ist schlicht und einfach ungültig. Das hat keine Aussagekraft, du musst eine echte Begrenzung angeben (keine ?).
 
G

Guest

Gast
:shock: Hmm.. so geht es.
Kannst Du bitte ein Beispiel für das "? etends Whatever" zeigen?
Mir ist der Unterschied nicht ganz klar.

Danke.
 
B

Beni

Gast
Eine Methode wie das hier:
Code:
public void doSomething( List<? extends Number> list){
  for( ...  // z.B. ein System.out.println für alle Nummern
}

Kann auch mit einem "Vector<Double>" aufgerufen werden.

Würde es nur "List<Number> list" heissen, wäre das nicht möglich. (Denn dann könnte man in dieser doSomething-Methode z.B. Integer in die Liste schieben, was für den Vector<Double> nicht gut wäre)
 
S

stev.glasow

Gast
Beispiel :
Code:
public static void foo(List<Number> numbers)
{
  for (Number s : numbers) {
     System.out.println(s.doubleValue());
   }
}

public static void bar(List<? extends  Number> numbers)
{
  for (Number s : numbers) {
     System.out.println(s.doubleValue());
   }
}

...

List<Number> a = new LinkedList<Number>();
a.add(1);
a.add(1.1);

List<Integer> b = new LinkedList<Integer>();
b.add(1);
b.add(2);

foo(a);
foo(b); // nicht möglich da explizit ein Typ 'List<Number>' erwartet wird.
bar(a);
bar(b); // ist möglich, da Integer von Number erbt

Klor?
[edit] ah Beni war wesentlich schneller.
 
G

Guest

Gast
Danke, jetzt hab ich es endlich geschnallt ;-)
Code:
public void ausgabe(List<? extends Number> list) {
  ...
}

List<Integer> l1 = new ArrayList<Integer>();
...
List<Double> l2 = new ArrayList<Double>();
...
ausgabe(l1);
ausgabe(l2);
Das "extends" bezieht sich auf den Typen der Liste. In der Methode "ausgabe"
werden alle List-Objekte akzeptiert, deren Element von Number abgeleitet sind.

Sachen gibt's :lol:
 
S

stev.glasow

Gast
Wieso ist eigentlich nicht gleich alles automatisch "? extends Blub" ?
 
S

stev.glasow

Gast
Wie meinst das?
Casten muss ich doch hier auch nicht:
Code:
public static void bar(List<? extends  Number> numbers)
{
  for (Number s : numbers) {
     System.out.println(s.doubleValue());
   }
}
 
G

Guest

Gast
Mal auf die Gefahr hin, dass wie aneinander vorbei reden. :wink:

Angenommen, man hat ein Framework, wie das Commons-Collections von Apache,
wo irgendwelche ausgefallene Methoden zur Manipualation von Zahlenreihen vorhanden
sind. Das Framework arbeitet z.B. mit allen Typen zusammen, die von Number erben.
In Deinem Programm verwendest Du aber nur Integer, möchtest trotzdem das Framework
verwenden. Die Methoden des Frameworks haben dann eine Signatur wie
Code:
public static void doSomeCrazyStuff(List <? extends Number> list);
Du verwendest es aber mit
Code:
List<Integer> list = new ArrayList<Integer>();
ein anderer wieder mit
Code:
List<Double> list = new ArrayList<Double>();
Ich denke, dass dies der Unterschied ist.
Bei
Code:
public static void doSomeCrazyStuff(List <Number> list);
müsstest Du List<Number> übergeben und u.U. zig Casts in Deinem Code verwenden.

Korrigiert mich bitte, wenn etwas falsch ist. Ich denke aber, ich hab' es endlich kapiert. :wink:
 
S

stev.glasow

Gast
Ich würde gern wissen warum die Einschränkung ohne extends besteht.

Außerdem verstehe ich immer noch nicht was du mit dem Casten sagen willst. Um in der Methode doSomeCrazyStuff, egal welche Variante, die Elemente als int vorliegen zu habem muss ich die Casten:
int x = (int)dieListe.get(1122); // <<< hier musst du bei beiden Varianten casten, egal ob 'dieListe' mit oder ohne extends übergeben wurde (mal davon abgesehen, dass das sehr unschön ist). Oder meintest du was anderes?
 
G

Guest

Gast
Ich meine das, was Du in Deinem Beispiel mit den zwei Methoden 'foo' und 'bar' gezeigt hast.
Bei der Variante mit 'List<? extends Number>' als Parameter kannst Du jede Liste übergeben,
deren Elemente von Number erben. Ohne '<? extends Number>', also mit 'List<Number>' als
Parameter, bist Du gezwungen 'List<Number>' an die Methode zu übergeben und musst außerhalb
der Methode
wie wild casten, wenn Du verschiedene Typen verwenden möchtest.
Oder anders ausgedrückt, eine Methode mit der Signatur
Code:
public void a(List<Number> list);
akzeptiert nur 'List<Number>' als Parameter.
Eine Methode mit der Signatur
Code:
public void a(List<? extends Number> list);
akzeptiert die Typen List<Integer|Double|Long usw.>
 
S

stev.glasow

Gast
Achso außerhalb. Da hast du recht, List<Integer> in List<Number> umzuformen wäre mies. Das erklärt aber nicht warum ohne extends eine Beschränkung besteht, darfür muss es doch einen Sinn geben. :bahnhof:
 
G

Guest

Gast
Ich denke, dass der Unterschied einfach daran liegt, dass man ohne 'extends' einen
bestimmten Typen von List erzwingt.
So gesehen macht List<? extends Number> wenig Sinn, müsste schon konkreter sein
(Integer etc.).

Ein zweiter, nicht unbedeutender, Unterschied ist dann der Inhalt. Bei List<Number>
kannst Du in der Methode eine gemischte Liste erwarten (verschiedene Typen von Daten drin),
bei List<? extends Number> werden zwar verschiedene List-Typen akzeptiert aber deren
Elemente sind alle garantiert vom gleichen Typ (bzw. Basistyp).

Die Verwirrung entsteht, denke ich, durch das Schlüsselwort 'extends'.
Es bezieht sich nicht auf die Java-Syntax im Sinne von 'Integer extends Number' sondern
'ParameterTypB extends ParameterTypA'. Oder so ähnlich :wink:
Denk da an einen Preprocessor, der vor dem eigenlichen Compilieren zuerst den Code
von Preprocessor-Anweisungen und Templates 'bereinigt' und den zu compilierenden
Code generiert.

Ich glaube, wenn ich noch weiter darüber nachdenke, wird ein Buch draus "Me against the generics" :lol:
 
S

stev.glasow

Gast
Bei List<Number>
kannst Du in der Methode eine gemischte Liste erwarten (verschiedene Typen von Daten drin),
bei List<? extends Number> werden zwar verschiedene List-Typen akzeptiert aber deren
Elemente sind alle garantiert vom gleichen Typ (bzw. Basistyp).
:bahnhof:
Bei List<? extends Number> kann ich auch eine Liste vom Typ List<Number> übergeben

Wieso erklärst du mir das eigentlich ständig? Ich will wissen warum es diese Einschränkung gibt wenn kein extends angegeben wurde.

Entweder verstehen wir uns miss oder (min) einer von uns beiden sieht nicht durch. :roll:
 
G

Guest

Gast
stevg hat gesagt.:
Bei List<? extends Number> kann ich auch eine Liste vom Typ List<Number> übergeben
Als eine von vielen Möglichkeiten. Bei List<Number> hast Du nur die eine.
stevg hat gesagt.:
Wieso erklärst du mir das eigentlich ständig? Ich will wissen warum es diese Einschränkung gibt wenn kein extends angegeben wurde.
Bleib cool, ich versuche nur zu antworten. Jeder denkt in etwas anderen Bahnen, so dass es schwierig ist, den Gedankengänge eines anderen zu folgen.
stevg hat gesagt.:
Entweder verstehen wir uns miss oder (min) einer von uns beiden sieht nicht durch. :roll:
Beides. Wir sind mental inkompatibel. :wink:
 
S

stev.glasow

Gast
OK, ich bleib cool.

Anonymous hat gesagt.:
stevg hat gesagt.:
Bei List<? extends Number> kann ich auch eine Liste vom Typ List<Number> übergeben
Als eine von vielen Möglichkeiten. Bei List<Number> hast Du nur die eine.
Das wusste ich bereits, denn ich und Beni haben dir das ja so erklärt. Und die Tatsache dass man auch eine Liste vom Typ List<Number> übergeben kann und diese Ausage
Bei List<Number>
kannst Du in der Methode eine gemischte Liste erwarten (verschiedene Typen von Daten drin),
bei List<? extends Number> werden zwar verschiedene List-Typen akzeptiert aber deren
Elemente sind alle garantiert vom gleichen Typ (bzw. Basistyp).
wieder sprechen sich meiner Meinung nach.
 
G

Guest

Gast
stevg hat gesagt.:
Bei List<Number>
kannst Du in der Methode eine gemischte Liste erwarten (verschiedene Typen von Daten drin),
bei List<? extends Number> werden zwar verschiedene List-Typen akzeptiert aber deren
Elemente sind alle garantiert vom gleichen Typ (bzw. Basistyp).
wieder sprechen sich meiner Meinung nach.
Ehm.. wo Du es schreibst. Sollte umgekehrt sein und zwar wegen:
Code:
public void a(List <Number>list) {
  list.add(Integer.valueOf(1)); // OK. Alle Elemente sind garantiert von Number abgeleitet.
  ...
}

public void a(List <? extends Number>list) {
  list.add(Integer.valueOf(1)); // funktioniert nicht, da list auch List<Double> o.a. sein kann
  ...
}

???:L
 
S

stev.glasow

Gast
Stimmt, war mein Fehler.
Beni hat mir das grad klar gemacht.
Chat hat gesagt.:
13:44:11 Beni: muss mal gucken
13:45:08 stevg: wenn nicht ist's auch ok
13:45:40 Beni: ach so, um beim List<Number>-Bsp zu bleiben: wenn du da z.B. eine List<Double> rein schieben könntest, könntest du dieser List<Double> eine beliebige Number, z.B. ein Integer, einfügen, und so was falsches produzieren
13:46:38 stevg: stimmt
13:47:11 Beni: und das gibt diese Einschränkung, damit man diesen Fehler nicht machen kann
13:47:35 stevg: jo jetzt ist's klar, ich bin immer davon ausgegangen, das man von dem argument nur lesen will
13:47:52 Beni: ok :)
13:48:23 stevg: :)
 
G

Guest

Gast
Was wäre das Forum ohne Beni? :wink:

Ich denke, wir haben jetzt schon alle Besonderheiten der Syntax
durch. Oder fällt Dir noch etwas ein, was hier fehlt?
 

Ebenius

Top Contributor
Also der Grund ist ganz einfach.

Folgendes Beispiel: Ich möchte eine Methode haben, die in eine Collection eine Nummer einfügt, es sei denn, die Nummer ist durch 4 teilbar.
Hier funktioniert <? extends T> nicht.
Code:
 void insertNumber(List<Number> l, Number n) {
   if(n.intValue() % 4 != 0)
     l.add(n); // geht, die Liste kann Numbers beinhalten und bekommt Number
 }

 /* NOPE */
 void insertNumberExtends(List<? extends Number> l, Number n) {
   if(n.intValue() % 4 != 0)
     l.add(n); // geht nicht, weil die Liste ArrayList<Double> sein könnte,
               // n vielleicht vom Typ Integer und die beiden passen einfach
               // nicht zusammen!
 }

 void insertNumberSuper(List<? super Number> l, Number n) {
   if(n.intValue() % 4 != 0)
     l.add(n); // geht, die Liste kann Objects, Numbers beinhalten und n ist
               // kompatibel
 }

Hier funktioniert jetzt <? extends T> nicht.
Code:
 Number getFirstNumber(List<Number> list) {
   return list.get(0); // geht, list enthält Numbers
 }

 Number getFirstNumberExtends(List<? extends Number> list) {
   return list.get(0); // geht, list enthält Doubles, Integers, ...
 }

 /* NOPE */
 Number getFirstNumberSuper(List<? super Number> list) {
   return list.get(0); // geht nicht, da in dieser Liste auch Object-Instanzen
                       // sein können (die nicht mit dem R374ckgabewert der
                       // Methode kompatibel sind)
 }

Klar, soweit?

Cheers!
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
Kirby.exe Vererbung bei Generics Allgemeine Java-Themen 7
W Generics + Vererbung Allgemeine Java-Themen 47
kaoZ Generics und Vererbung Allgemeine Java-Themen 3
F Google Guice + Generics + Vererbung Allgemeine Java-Themen 5
J Best Practice Generics mit Enum Allgemeine Java-Themen 3
H Kombination Interface und Abstrakte Klasse bei Generics Allgemeine Java-Themen 3
Zeppi Cast Object in Generics Allgemeine Java-Themen 4
P Generics und Arrays Allgemeine Java-Themen 6
M Generics / Typen Allgemeine Java-Themen 1
Kirby.exe InsertionSort mit Generics Allgemeine Java-Themen 33
H Klarnamen etc... (von Wie Generics lernen?) Allgemeine Java-Themen 26
D Wie Generics lernen? Allgemeine Java-Themen 26
L Compiler-Fehler Generics beim Anhängen von Predicates Allgemeine Java-Themen 1
W Vererbung Generics - mal wieder die verhaßte Rückwärtskompatibilität Allgemeine Java-Themen 2
S Verstaendnisfrage Generics Allgemeine Java-Themen 19
I Methoden Generics-Methode Allgemeine Java-Themen 3
D Mit Generics arbeiten - Übungsaufgabe Allgemeine Java-Themen 3
K Factory Pattern: Mit Generics umgehen Allgemeine Java-Themen 6
G Generics Allgemeine Java-Themen 31
perlenfischer1984 Liste mit generics zurück liefern Allgemeine Java-Themen 8
Hacer Generics & Collections Allgemeine Java-Themen 8
Neumi5694 Interface Generics für Enum-Filterung verwenden Allgemeine Java-Themen 5
H Collector Generics Problem (incl. Stream & Lambda) Allgemeine Java-Themen 4
C Gemeinsame Oberklasse zweier Generics Allgemeine Java-Themen 10
erdmann Datentypen Methodendeklaration mit Generics Allgemeine Java-Themen 2
Z Datentypen Verschachtelte Generics Allgemeine Java-Themen 1
Neumi5694 Datentypen Generics Allgemeine Java-Themen 5
S Mit Generics Klasse erstellen die selbst T erweitert..? Allgemeine Java-Themen 4
Tarrew Generics - Type erasure Allgemeine Java-Themen 5
N Problem mit Generics und Interface Allgemeine Java-Themen 4
H Generics als Parameter Allgemeine Java-Themen 1
A Datentypen Generics: Wie am besten auf Typparameter zugreifen Allgemeine Java-Themen 2
C Generics Objekt in ArrayList Allgemeine Java-Themen 2
vandread Kleine Generics Aufgabe aus einer Prüfung... wie ist das gemeint? Allgemeine Java-Themen 6
G Generics sind zu streng - oder ich zu naiv? Allgemeine Java-Themen 3
G Verschachtelte Generics Allgemeine Java-Themen 2
O Generics Allgemeine Java-Themen 42
M Problem mit Generics Allgemeine Java-Themen 10
M Generics (bounded wildcards statt Interface Bezeichnern) -- Sinn oder Unsinn? Allgemeine Java-Themen 2
darekkay Generics: Wildcard und Object Allgemeine Java-Themen 5
H Collections Generics und Reflection Allgemeine Java-Themen 6
H Problem mit Java Generics Allgemeine Java-Themen 6
J Generics: Typparameter als Klasse zurückliefern Allgemeine Java-Themen 4
H Generics Allgemeine Java-Themen 5
P Probleme mit Generics Allgemeine Java-Themen 5
B Generics und primitve arrays Allgemeine Java-Themen 6
M Generics Allgemeine Java-Themen 11
1 Collections Generics, internes Verhalten Allgemeine Java-Themen 16
T Warnungsfreie Verwendung von Generics Allgemeine Java-Themen 11
M Probleme mit Generics Allgemeine Java-Themen 5
D Java Generics Allgemeine Java-Themen 8
2 Generics: bounded wildcards Allgemeine Java-Themen 4
J Generics / vermeiden von downcasts Allgemeine Java-Themen 2
2 Generics oder nicht? Allgemeine Java-Themen 8
E Problem mit Generics und Comparable Allgemeine Java-Themen 16
W Erweitern einer Klasse mit Generics Allgemeine Java-Themen 8
H Generics für Methode Allgemeine Java-Themen 14
N Überladen mit Hilfe von Generics Allgemeine Java-Themen 3
S Generics: Fuer Set<T> ein T-Klassenobjekt erhalten? Allgemeine Java-Themen 3
Q Der innere Typ von Generics? Allgemeine Java-Themen 3
N Generics-NullpointerException Allgemeine Java-Themen 7
2 Generics - Typ Allgemeine Java-Themen 12
P Generics Problem Allgemeine Java-Themen 10
S Type safety Warnings beim casten von Generics Allgemeine Java-Themen 6
N Generics Allgemeine Java-Themen 3
V Frage zu Generics Allgemeine Java-Themen 2
S java generics klassen deklaration Allgemeine Java-Themen 7
B hashtable für unterschiedliche Typen - mit Generics Allgemeine Java-Themen 8
E Generics Allgemeine Java-Themen 3
MQue Generics Allgemeine Java-Themen 4
R Problem mit Reflection und Generics Allgemeine Java-Themen 3
C Klassen, die aufeinander verweisen (mit Generics) Allgemeine Java-Themen 16
G Generics - W.card unter Nutzung von Annotationsklasse? Allgemeine Java-Themen 6
G sortieren von generics Allgemeine Java-Themen 10
G Generics in Map. Type of value abhängig vom key Allgemeine Java-Themen 3
A Generics Verständnisfrage Allgemeine Java-Themen 7
Z Generics funzt nicht? Allgemeine Java-Themen 2
T Generics Allgemeine Java-Themen 18
G ComboBox: Nur eine Art Klasse zulassen (Generics) Allgemeine Java-Themen 3
J Generics Expertenwissen? Allgemeine Java-Themen 5
S Generics-Problem Allgemeine Java-Themen 3
T Generics und Wil-dcards Allgemeine Java-Themen 8
Q Typen von Generics & Casten Allgemeine Java-Themen 3
S Generics Allgemeine Java-Themen 2
R Problem mit Generics Allgemeine Java-Themen 2
G Trotz Generics Cast-Fehler! Allgemeine Java-Themen 5
T TreeMap durch Comparator mit Generics sortieren Allgemeine Java-Themen 9
T Generics und instanceof Allgemeine Java-Themen 10
T Generics und Exceptions Allgemeine Java-Themen 6
M Beliebig viele Typen bei Generics Allgemeine Java-Themen 3
G Reflection objekt mit generics erzeugen Allgemeine Java-Themen 5
S Singleton Pattern mit Generics Allgemeine Java-Themen 4
G Generics und Comparable Allgemeine Java-Themen 11
H Generics Problem Allgemeine Java-Themen 3
F Generics: spricht etwas dagegen raw types zu verwenden? Allgemeine Java-Themen 31
M Generics - besser programmieren, Warnung umgehen Allgemeine Java-Themen 4
E Java, UML, Generics Allgemeine Java-Themen 6
P Array von Vectoren + Generics Allgemeine Java-Themen 6
M ArrayList erweitern - generics Allgemeine Java-Themen 4
E Generics -> UML Allgemeine Java-Themen 4

Ähnliche Java Themen

Neue Themen


Oben