Datentypen Generischen Typ instanzieren

Holger_Hessling

Aktives Mitglied
Hallo Forum,

ich möchte eine Liste von Objekten verwalten, zu denen zusätzliche Daten gespeichert werden. Drum hab ich das in eine eigene Klasse gepackt und diese generisch gemacht. Das sieht jetzt mal so aus:
Code:
public class DOList<T extends DOElement> {

   private DOTauchgang tg;
   private List<T> list = new ArrayList<>();
   private Integer activeIndex;
   private List<DOListListener> listener = new ArrayList<>();

   public DOList(DOTauchgang tg, String label) {
     super(label);
     this.tg = tg;
     activeIndex = null;
   }
}
Der Datentyp T ist einer aus fünf möglichen, die jeweils von DOElement abgeleitet sind. Somit sind jetzt nur Listen mit diesen fünf Typen möglich.
Was ich jetzt leider nicht hinbekomme, daß ich in einer Klassenmethode (z. B. im Konstruktor) ein neues Objekt vom Typ T instanziiere. Also sowas zum Beispiel:
Code:
    T newElement = new T();
    list.add(newElement);
Ich würde erwarten, daß eines der fünf möglichen Objekte erzeugt wird, auf Grundlage des Typs T, mit dem die DOList instanziiert wurde. Aber das geht nicht. Mache ich etwas falsch oder ist das prinzipiell nicht möglich?

VG Holger
 

tommysenf

Top Contributor
Das funktioniert generell nicht, man nicht davon ausgehen kann, dass alle von DOElement abgeleiteten Klassen einen Standardkonstruktor besitzen.

und welches denn? Woher soll Java wissen, welches der 5 Typen du willst?

Das ist eigentlich für Java klar, der Typ steht ja im Typparameter T.

P.S: Ich glaube in Java 9 soll es demnächst Lösungen für dieses Problem geben, bin mir da jetzt aber nicht ganz sicher.
 

thecain

Top Contributor
Nein, die Liste hat ja den generischen Typenparameter und der Liste will er ein Objekt hinzufügen, ausserhalb von der Liste ist aber T aber unbekannt.

Ausser ich verstehe die Codeschnippsel falsch
 

Kababär

Top Contributor
Also ich frage mich sowieso wieso er das generisch macht. Wenn 5 Klassen DOElement extenden, kann ich doch alle Klassen als DOElement instanziieren und in die Liste packen. (List<DOElement>).
 

tommysenf

Top Contributor
Also ich frage mich sowieso wieso er das generisch macht. Wenn 5 Klassen DOElement extenden, kann ich doch alle Klassen als DOElement instanziieren und in die Liste packen. (List<DOElement>).

Weil es etwas anderes ist:

List<DOElement> : Liste von beliebigen DOElement Typen
List<? extends DOElement > : Liste von einem bestimmten DOElement Typ
 

stg

Top Contributor
Um der Problemlösungmal ein wenig näher zu kommen:
Ich mache das dann so, dass ich entweder im Konstruktor eine Class-Referenz auf den konkreten Typ übergebe, oder der Typ selbst bekommt eine Factory-Methode, bzw man übergibt eine Factory-Klasse.

Der einfachste Fall sieht dann etwa so aus
Java:
public class Foo<T> {
    private Class<T> clazz;

    public Foo(Class<T> clazz){
        this.clazz = clazz;
    }

    public T createInstance() throws InstantiationException, IllegalAccessException {
        return clazz.newInstance();
    }
}
 

Flown

Administrator
Mitarbeiter
P.S: Ich glaube in Java 9 soll es demnächst Lösungen für dieses Problem geben, bin mir da jetzt aber nicht ganz sicher.
Nö, reified types werden bestimmt nicht kommen.

Ich würde das eher so machen (mit Java 8) einen Supplier<T> übergeben und dann einfach eine Instanz kreieren lassen, ohne unnötige Reflections:
Java:
public final class Factory<T> {
  private final Supplier<T> generator;
  
  public Factory(Supplier<T> generator) {
    Objects.requireNonNull(generator);
    this.generator = generator;
  }

  public T createInstance() {
    return generator.get();
  }
}
Aufruf dann mit einer (Sub-)Klasse:
Java:
Factory<DOElement> factory = new Factory<>(SubDOElement::new);
 

Holger_Hessling

Aktives Mitglied
Hallo Leute,

wow, da hab ich ja eine Diskussion angeregt :) Leider war ich gestern Abend verhindert und lese Eure Beiträge erst heute. Offenbar ist dieses "Problem" durchaus bekannt und offenbar gibt es dafür (sehr spezielle) Lösungen. Die angeregten Lösungen muß ich mir heute Abend mal in Ruhe ansehen und versuchen zu verstehen (bin halt doch Anfänger ;)).

Vielen Dank für Eure Antworten!!!!!

VG Holger
 

Holger_Hessling

Aktives Mitglied
Hallo Forum,

durch Eure guten Beiträge konnte ich mein Problem lösen. Angeregt durch die Beispiele mit den Java Reflections habe ich ein wenig darüber gelesen und hab meine eigenen Listen-Klasse jetzt so angelegt:
Code:
public class DOList<T extends DOElement> extends DataObject {

   private Class<T> listType;
   private DOTauchgang tg;
   private List<T> list = new ArrayList<>();
   private List<DOListListener> listener = new ArrayList<>();

   public DOList(Class<T> listType, DOTauchgang tg, String label) {
     super(label);
     this.listType = listType;
     this.tg = tg;
   }

   private T newInstance() {

     Constructor<T> constructor = null;
     try {
       constructor = listType.getConstructor(String.class);
     } catch (NoSuchMethodException | SecurityException e) {
       e.printStackTrace();
     }

     T newElement = null;
     try {
       newElement = constructor.newInstance("new '" + listType.getSimpleName() + "'");
     } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
         | InvocationTargetException e) {
       e.printStackTrace();
     }
     return newElement;
   }

  public void newElement() {

     T newElement = newInstance();
     newElement.setList(this);
     setAllInactive();
     newElement.setActive();
     list.add(newElement);

     for (DOListListener l : listener) {
       l.elementAdded(this.tg, this, newElement);
     }

   }
Mit dieser Konstruktion ist es möglich, einer Instanz der Klasse DOList<T extends DOElement> über ihre Methode newElement() anzuweisen, sich selbst ein neues Element zu erzeugen und der eigenen Liste hinzuzufügen. Und das auf der Basis des Typs <T> beim instanziieren der DOList. :)

Ich habe durch Euch wieder viel gelernt. Vielen Dank nochmal!!!!

VG Holger
 

Flown

Administrator
Mitarbeiter
Ist jetzt aber keine Lösung auf die du stolz sein solltest! Mittels Reflections ein Objekt erzeugen ist hier komplett übertrieben, denn du kennst ja den Konstruktor!
Hier wäre eine Factory eindeutig die bessere Wahl.
 

Holger_Hessling

Aktives Mitglied
Hm, war eigentlich schon stolz, wieder etwas gelernt zu haben :) Hättest Du Lust, mir Deinen Vorschlag etwas deutlicher zu machen? Deinen Code aus Deiner vorletzten Antwort verstehe ich leider nicht.

VG Holger
 

Flown

Administrator
Mitarbeiter
Ist jetzt zwar ein Sinnlosbeispiel (ähnlich gehalten wie deine Klassen):
Java:
public class Test {
  public static void main(String... args) {
    TypeList<SubType> list = new TypeList<>(new TypeFactory<SubType>() {
      @Override
      public SubType create() {
        return new SubType(SubType.class.getSimpleName());
      }
    });
    list.newElement();
  }
 
}

interface TypeFactory<T extends Type> {
  T create();
}

abstract class Type {
  private String instanceName;
 
  public Type(String instanceName) {
    this.instanceName = instanceName;
  }
 
  @Override
  public String toString() {
    return instanceName;
  }
}

class SubType extends Type {
 
  public SubType(String instanceName) {
    super(instanceName);
  }
}

class TypeList<T extends Type> {
  private TypeFactory<T> factory;
 
  public TypeList(TypeFactory<T> factory) {
    this.factory = factory;
  }
 
  public void newElement() {
    T element = factory.create();
    System.out.println(element);
  }
}
EDIT: Mit Java 8 geht das auch so:
Java:
public class Test {
  public static void main(String... args) {
    TypeList<SubType> list = new TypeList<>(() -> new SubType(SubType.class.getSimpleName()));
    list.newElement();
  }
}
 

Holger_Hessling

Aktives Mitglied
Hi Flown, (wie ist Dein Name? :))

vielen Dank für Deine Mühe!!!! Das Beispiel funktioniert. Ich hab's mal auf meine Klassennamen verändert und um meine Klassen erweitert. Diese Konstruktion hätte ich noch lange nicht selbst ausbrüten können. Mit dem Verstehen Deines Beispiels habe ich auch meine Problemchen :rolleyes: Aber anhand Deines Beispiels werde ich mich durchhangeln!!!! Irgendwann wird der Groschen schon fallen.

Dein EDIT habe ich auch ausprobiert. Das ist das Thema Lamdas und funktionale Interfaces. Die durchblicke ich ebnefalls noch nicht. Aber Dein Beispiel funktioniert auch nicht. Leider! Den Fehler kann ICH natürlcih noch nicht finden :D:D

VG Holger
 

Holger_Hessling

Aktives Mitglied
Hallo Florian,

so langsam durchblicke ich auch dieses Designpattern mit der Factory. Findet man ja einiges im Netz. Schöne Sache. Jetzt hab ich sogar einen Einstieg in Lambda-Expressions gehabt und setze sie in meinem Programme in.
(jetzt bin ich wieder stolz ;))

VG Holger
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
A Generischen Klassen Java Basics - Anfänger-Themen 8
W Vergleiche bei generischen Datentypen Java Basics - Anfänger-Themen 7
D generischen Sammlung Java Basics - Anfänger-Themen 29
Shizmo Frage zu generischen Arrays Java Basics - Anfänger-Themen 3
G Was ist der Nutzen von generischen Konstruktoren? Java Basics - Anfänger-Themen 4
M Datentypen Konstruktor mit generischen Parametern überladen Java Basics - Anfänger-Themen 3
H Collections Array mit generischen Typ Java Basics - Anfänger-Themen 11
X eigener Mergesort auf generischen Typen mit Comparator Java Basics - Anfänger-Themen 6
Z Problem mit Ausgabe eines generischen Suchbaums Java Basics - Anfänger-Themen 3
G Class eines Generischen Datentyps? Java Basics - Anfänger-Themen 6
T Vergleich von generischen Typen Java Basics - Anfänger-Themen 2
F Generische Liste von generischen Objekten. Java Basics - Anfänger-Themen 3
A Array mit generischen Typen casten? Java Basics - Anfänger-Themen 6
T Klassen Denkfehler im Klassen "dynamisch" instanzieren? Java Basics - Anfänger-Themen 4
E Instanzieren von Objekten verkürzen Java Basics - Anfänger-Themen 1
F Abstrakte Klasse doch zum "Teil" instanzieren? Java Basics - Anfänger-Themen 4
M OOP Klasse mit Superklasse instanzieren Java Basics - Anfänger-Themen 3
A List Array - wie instanzieren Java Basics - Anfänger-Themen 7
T Anwendereigene Variablen instanzieren? Java Basics - Anfänger-Themen 18
bigbasti Mehrdimensionales Array instanzieren Java Basics - Anfänger-Themen 10
M instanzieren einer abstrakten Klasse? Java Basics - Anfänger-Themen 2
G aus hashmap klassen instanzieren Java Basics - Anfänger-Themen 19
G Instanzieren von Objekten Java Basics - Anfänger-Themen 2
D .Class instanzieren Java Basics - Anfänger-Themen 2
G methode um Klasse zu instanzieren Java Basics - Anfänger-Themen 5
G instanzieren Java Basics - Anfänger-Themen 2
D Klasse in einer anderen instanzieren Java Basics - Anfänger-Themen 3
L JOptionPane instanzieren oder nicht? Java Basics - Anfänger-Themen 7
J Objekt instanzieren Java Basics - Anfänger-Themen 3
T Instanzieren von Objekten Java Basics - Anfänger-Themen 4

Ähnliche Java Themen

Neue Themen


Oben