Java: Objekt von generischem Typ erzeugen

Palladin007

assimiliert
Moin,

mein Problem ist einfach beschrieben:

c#:
Code:
public static T CreateGenericObject<T>()
    where T : new()
{
    return new T();
}

Java:
???


Ich such jetzt schon eine ganze Weile und habe über verschiedene Wege probiert, wobei mir allerdings meine spärlichen Java-Kenntnisse etwas im Weg standen.
Anforderung ist einfach, dass ich ein Objekt von einem generischen Typ benötige, ohne Parameter, ganz simpel, aber scheinbar gibt es so etwas nicht in Java.
Kennt jemand einen sauberen Weg, wie ich das lösen kann?


Gruß
 
Zuletzt bearbeitet:
Ich kenne Java ja leider auch nicht, aber mein erster Gedanke war in Erinnerung an Pascal, dass das mit einem allgemeinen Pointer gehen könnte. Aber die Objekte sind eigentlich alle schon von diesem Typ, wie du hier lesen kannst. Aber vielleicht liefert dir dieses Stichwort dennoch wenigstens einen Anhaltspunkt, damit du weiter kommst.
 
Du willst also in deinem Code lieber eine Methode aufrufen, anstelle mit 'new' einfach ein neues Object zu erstellen? Also schreibst du dann 'CreateGenericObject<MeinTyp>'
anstelle von 'new MeinTyp()' ?

Was liefert deine c# Methode eigentlich zurück, wenn der Typ keinen parameterlosen Konstruktor zur Verfügung stellt?

ot:

Ich musste spontan an das Bild im Beitrag von Thor77 denken: https://www.supernature-forum.de/comedy-and-spiele/56233-witzige-bilder-149.html#post1097940
 
Naja, zuallererst brauche ich den Typ des generischen Objektes um anschließend die Annotations einzelner Felder abzufragen und dann ein Objekt dieses Typs zu erstellen.
Beides nutze ich dann für die Weiterverarbeitung. Natürlich kann ich dann auch hin gehen und den Typ als Parameter mit geben, allerdings würde sich das dann zu anderen Parametern gesellen, was mir nicht gefällt und wofür sind Generics denn sonst da?

Es würde auch noch andere Möglichkeiten geben, so verlangt die generische ToArray-Methode zum Beispiel ein Array mit dem generischen Typ als Parameter. Ich würde glatt wetten, dass sie auf diese Weise dann einfach den Typ bekommen und dann entsprechend arbeitet.
Aber auch das würde sich dann in den Parametern wieder finden und das möchte ich vermeiden.


Was die Pointer angeht:
Ich glaube, das geht in Java gar nicht, oder? Bei C# kein Problem, da muss ich nur unsafe erlauben und entsprechende unsafe Bereich deklarieren und ich habe meine Pointer in ihrem vollen Umfang.
Aber selbst wenn Java das kann, würde ich das gerne vermeiden, da ich kaum Erfahrung in der Arbeit mit Pointern habe und sich auch zu viele Fehlerquellen dazu gesellen.
Außerdem soll das Ganze am Ende dann auf Linux fehlerfrei laufen können, was bedeutet, ich kann es nicht testen und da ich mit den reinen Pointern arbeite, kann ich mich nicht darauf verlassen, dass die RE alles regelt.




Kann auch sein, dass ich zu sehr an C# gewöhnt bin und so total simple Dinge, wie new T() oder typeof(T) mal eben das machen, was in Java nun schon einige Stunden Überlegen ohne Ergebnis verschlungen hat.
 
Ok, hab die letzten Stunden noch was mit Ausprobieren und Suchen verbracht und immer öfter gelesen, das geht nicht.

Meine "Lösung" daher, für eventuell Suchende:

Code:
public static <T> T CreateInstance(Class<T> type) throws InstantiationException, IllegalAccessException
{
    return type.newInstance();
}

So hässlich ist das aber nun auch nicht, es wird so genutzt:

Code:
MyType var = CreateInstance(MyType.class);

Und ja, das mag sinnlos erscheinen, ist aber auch nur eine Beispiel-Methode für einem größeren Zusammenhang ^^
 
Ich wollte nur verstehen, was du erreichen willst. Ich wollte aber definitiv nicht deine Vorgehensweise kritisieren.

Generics sind natürlich eine gute Sache, um ähnlich strukturierte Objekte mit der gleichen Methode zu behandeln. Um Instanzen zu erstellen werde
ich allerdings eher nicht auf einen generischen Ansatz zurückgreifen. Da würde ich den objektorientierten Ansatz mit Polymorphismus gehen. Falls der
Typ erst zur Laufzeit bekannt wird, würde ich eine oder mehrere Factory-Methoden erstellen.
 
Na wenn ich das über den Polymorphismus-Ansatz mache, dann fröhliches Klassen schreiben :D
Mir geht es um Felder mit bestimmten Annotations, die dann einen bestimmten Wert erhalten.
Ich wüsste nicht, wie ich das polymorph regeln könnte :D

Annotations kann ich auch gar nicht objektorientiert behandeln. Ich weiß es nicht sicher, aber bei dem C#-Äquivalent Attribut ist es so, dass das nur Metadaten sind, die so mit kompiliert werden. Da funktioniert kein objektorientierter Ansatz mehr.
Die sind dafür da, Dinge für irgendetwas zu markieren, was ich dann vollständig unabhängig vom Typ abfragen kann, daher Generics.
 
Es führen viele Wege nach Rom... :D

Wenn du mit unterschiedlichen Objekten gleichartige Operationen durchführen musst, lässt sich das auch mit
dem Observator-Pattern lösen.

Ich habe in den letzten Jahren sehr viel fremden Code erweitert. Oft wurde da auf Teufel komm raus Funktionalität
ausgelagert, teilweise mit vollständiger Fallunterscheidung im generischen Code :rolleyes:
Sowas ist sehr schwer zu analysieren und zu warten.
 
Ok, das Pattern kannte ich, aber auch nur so vom Lesen


Passt aber glaube trotzdem nicht ^^
Um etwas konkreter zu werden: Ich möchte einen Command-Interpreter für Minecraft Bukkit schreiben.
So wie ich das bisher gesehen habe, wurden Commands entweder über eine lange Reihe if-Statements gelöst, die dann jeden Zustand abdecken, was ich ausgesprochen hässlich finde.
Mein Ziel ist daher, einen Interpreter zu schreiben, der die Informationen, die vom Server bei einem Command kommen, in ein jeweiliges Objekt speichern kann.
Weshalb ich keinen bereits geschriebenen Command-Interpreter nutze: Der muss mit Minecraft Bukkit spezifische Informationen umgehen können, außerdem möchte ich es einfach selber schreiben :D

Mein Vorgehen daher:
Ich schreibe ein Objekt, bei dem an einzelnen Feldern Informationen zu einem Command-Parameter hängen.
Die generische Methode, die ich schreiben möchte, sucht sich vom angegebenen Typ daher alle Felder mit dieser Annotation zusammen und setzt diese aus den Command-Informationen.

Eine andere Variante war, dass ich einen Wrapper schreibe, wo die Infos dann drin liegen und jede Command-Klasse erbt dann von einer abstrakten Klasse, die diese Wrapper-Objekte registriert und die genaueren Informationen preis geben kann.
Über Annotation wäre das aber deutlich überschaubarer, weil sich das Ganze dann auf eine Zeile über einem Feld beschränken würde.
Außerdem hab ich mir das von C# so ab geschaut, da Attribute dort häufiger für so etwas in der Art genutzt werden, man muss sich nur mal die ganzen ORMs anschauen, was die für Attribut-Massen überall stehen haben.
 
Das Thema ist ja nun schon ein paar Wochen alt, aber ich dachte mir, ich ergänze das mal noch um eine Info zu den Generics, ohne auf die fachliche Fragestellung einzugehen.

Im Gegensatz zu C# sind die Generics in Java in gewisser Hinsicht unterlegen. Das Problem ist, dass die JVM keine Generics kennt. Die Generics werden beim Kompilieren in Raw-Types verwandelt. Dieser Vorgang heißt Type Erasure. Dabei wird jeder generische Typ T durch Object ersetzt und ggf. gecastet. Das heißt ein
Code:
new T();
würde durch
Code:
new Object();
ersetzt. Daher mach ein Aufruf von new T() in Java einfach keinen Sinn und der Compiler meckert.
Daher muss man das in Java leider mittels Reflections lösen.

Meine Erklärung ist etwas vereinfacht. Mehr Details gibt es unter dem Link oben oder wenn man nach Java Type Erasure sucht.

Das ist leider eine große Schwäche von in Java. Sun hat sich aber damals gegen die Erweiterung der JVM um Generics entschieden, um die Kompatiblität des Java-Codes zu verschiedenen JVM-Versionen nicht zu gefährden. Wie dem auch sei, als Javaentwickler muss man mit der Sache leben.

Ich habe auch eine meiner Meinung sehr schöne kurze Erklärung der Unterschiede zwischen C#- und Java-Generics gefunden. Wer von der einen Sprache zur anderen wechselt, sollte sich den Unterschied bewusst machen.

So, ich hoffe, ich konnte etwas Licht ins dunklte bringen, warum das unter Java leider nicht klappt.
 
Oben