Ujiol: Verschachtelte Generics

Hallo,

Ich möchte in Java eigentlich folgendes machen:

List<List<String>> myList = new Vector<Vector<String>>();

Da meckert aber der Compiler. Folgendes funktioniert:

List<Vector<String>> mylist = new Vector<Vector<String>>();

Jetzt frage ich mich, warum ersteres nicht geht. Wenn jetzt jemand anderes als ich das Objekt "mylist" sieht und sich fragt "hm, was kann ich damit machen?", dann kann es ihm doch egal sein, ob ich das mit Vector oder ArrayList oder sonstwie instanziiert habe oder etwa nicht? Er müsste doch trotzdem z.B. ein myList.add(new ArrayList<String>()) machen können, immerhin sollte es dem Compiler egal sein, solange es ein Objekt einer Klasse ist, die vom List Interface erbt.
Hab ich hier einen Denkfehler?

  1. Hallo,

    verwende

    List<List<String>> stringList = new ArrayList<List<String>>();
    stringList.add(new ArrayList<String>());
    ...

    Vector wird eigentlich nicht mehr verwendet, weil man die Synchronisierung in der Regel nicht braucht und selbst wenn man sie braucht, man besser Collections.synchronizedList oder ähnliches verwendet.

    A<T> = B<T> geht, wenn A eine Superklasse von B ist
    A<T> = B<U> geht nicht, selbst wenn T eine Superklasse von B ist

    Gruß,
    andiv

  2. List<List<String>> myList = new Vector<Vector<String>>();
    Da meckert aber der Compiler. Folgendes funktioniert:
    List<Vector<String>> mylist = new Vector<Vector<String>>();
    Jetzt frage ich mich, warum ersteres nicht geht.

    Weil die Signaturen verschieden sind (iirc, nannte man dieses Typgedöhns Signaturen, oder waren das die Definitionen von Funktionen?)

    List<List<String>> würde bedeuten, dass man jegliche Instanzen dessen Klassen vom Typ List erben und String "verwenden" akzeptieren würde (Du könntest zB. ArrayList<String>- und Vector<String>-Instanzen reinstopfen). Durch Vector<Vector<String>> geht das aber nicht mehr, da ArrayList<String> halt kein Vector<String> ist.

    Trotzdem ist das was du willst möglich:
    List<? extends List<String>> myList = new Vector<Vector<String>>();

    Trotzdem bleibt new Vector<List<String>>() sinnvoller, da man nicht extra aufpassen muss was nun wirklich instanziert wurde.

    MfG
    bubble

    --
    If "god" had intended us to drink beer, he would have given us stomachs. - David Daye
    1. List<List<String>> myList = new Vector<Vector<String>>();
      Da meckert aber der Compiler. Folgendes funktioniert:
      List<Vector<String>> mylist = new Vector<Vector<String>>();
      Jetzt frage ich mich, warum ersteres nicht geht.
      Weil die Signaturen verschieden sind (iirc, nannte man dieses Typgedöhns Signaturen, oder waren das die Definitionen von Funktionen?)

      Afaik meinen Signaturien die... Eigenschaften von Funktionen (Parameter).

      List<List<String>> würde bedeuten, dass man jegliche Instanzen dessen Klassen vom Typ List erben und String "verwenden" akzeptieren würde (Du könntest zB. ArrayList<String>- und Vector<String>-Instanzen reinstopfen). Durch Vector<Vector<String>> geht das aber nicht mehr, da ArrayList<String> halt kein Vector<String> ist.

      Aber ich kann doch später irgendwann myList = new ...; machen und dann eben später doch ArrayLists reinstopfen. Jedenfalls rein logisch, das sollte keine Laufzeitfehler geben können imho.

      Trotzdem ist das was du willst möglich:
      List<? extends List<String>> myList = new Vector<Vector<String>>();

      Wie nennt man diese Syntax? Das "?" steht also für eine anonyme Klasse sozusagen?

      Danke auf jedenfall schonmal. =)

      1. Weil die Signaturen verschieden sind (iirc, nannte man dieses Typgedöhns Signaturen, oder waren das die Definitionen von Funktionen?)
        Afaik meinen Signaturien die... Eigenschaften von Funktionen (Parameter).

        List<List<String>> würde bedeuten, dass man jegliche Instanzen dessen Klassen vom Typ List erben und String "verwenden" akzeptieren würde (Du könntest zB. ArrayList<String>- und Vector<String>-Instanzen reinstopfen). Durch Vector<Vector<String>> geht das aber nicht mehr, da ArrayList<String> halt kein Vector<String> ist.

        Aber ich kann doch später irgendwann myList = new ...; machen und dann eben später doch ArrayLists reinstopfen. Jedenfalls rein logisch, das sollte keine Laufzeitfehler geben können imho.

        Das kommt halt drauf an. Eine List<List<String>> gibt halt bei den Funktionen immer ein List<String> zurück, beziehungsweise erwartet List<String>.
        Da kann ich halt meine ArrayList<String>- und meine Vector<String>-Instanzen reinstopfen.

        Eine Vector<Vector<String>> oder auch List<Vector<String>> verlangt halt immer Vector<String> als Parameter bzw, gibt Vector<String> zurück.
        Da kann ich nur noch meine Vector<String>-Instanzen reinstopfen.

        Trotzdem ist das was du willst möglich:
        List<? extends List<String>> myList = new Vector<Vector<String>>();
        Wie nennt man diese Syntax? Das "?" steht also für eine anonyme Klasse sozusagen?

        Wie man die Syntax genau nennt weiß ich auch nicht. Das ? ist sozusagen 'ne Wildcard und durch das "extends Class" wird einfach nur spezifiziert, dass der wirkliche Typ davon oder einer Sub-Klasse sein muss. Ich fand verwirrend, dass man auch "extends" verwenden muss wenn man ein Interface spezifiziert.

        Ich hoffe meine laienhaften Erklärungen konnten ein wenig Licht ins Dunkel bringen :')

        MfG
        bubble

        --
        If "god" had intended us to drink beer, he would have given us stomachs. - David Daye