ERLEDIGT
JA
JA
ANTWORTEN
4
4
ZUGRIFFE
570
570
EMPFEHLEN
-
Hallo zusammen,
Nachdem ich mich in letzer Zeit nur oberflächlich mit Java beschäftigt habe hat mich nun das Interesse gepackt mein nächstes Projekt, das ich eigentlich in C# - wie immer - programmieren wollten mal mit Java anzupacken.
Erwartungsgemäss funktioniert vieles eigentlich problemlos, da es doch nicht so gewaltige Unterschiede gibt zwischen den zwei Sprachen. Jedoch gibt es jetzt ein Problem mit generischen Typen. In C# ist es problemlos möglich von einem generischen Typen eine Instanz zu erstellen durch ein Constraint:
Der Typ den man nun an Generic übergibt muss nun einen parameterlosen Konstruktor besitzen und auch instanzierbar sein (kein Interface, keine abstrakte Klasse, ...). In Java habe ich das bisher nicht hinbekommen. Ist tatsächlich so, dass so etwas elementares nur über Umwege möglich ist, oder gibt es etwas vergleichbares? Bzw um genau zu sein habe ich es bisher noch nicht mal über Umwege hinbekommen eine Instanz von dem generisch angegebenen Typen zu erstellen.
Gruss
MuepeViele Tutorials und Artikel zur Programmierung unter Windows mit C++ und C#. Tägliche Updates und Antworten auf eure Fragen:
Win32Easy - Blog
Es würde mich freuen, wenn ihr einen Kommentar postet!
-
12.05.11 18:29 #2SE Tutorials.de Gastzugang
Also ohne mich jetzt selbst mit generischen Typen auszukennen würde ich meinen das sowas in Java nur mit Reflections möglich sein wird.
-
12.05.11 20:15 #3
- Registriert seit
- Jun 2002
- Ort
- Saarbrücken (Saarland)
- Beiträge
- 9.886
- Blog-Einträge
- 29
Hallo,
das was du machen willst (Erzeugung von generischen Typen) geht mit Java eigentlich nicht bzw. wird es von Java nicht direkt unterstützt. Jedoch ist es "prinzipiell" möglich das von dir gewünschte Verhalten nachzuahmen.
Generics in Java und C# sind unterschiedlich implementiert. Bei Java gibt es zur Laufzeit keine Informationen mehr zu Generics, denn diese werden vom Java Compiler (bis auf wenige Ausnahmen) entfernt (Stichwort: Type Erasure). Bei C# bleiben die Informationen zu Generics nach dem kompilieren erhalten und lassen sich zur Laufzeit auswerten.
Es gibt für Java ein paar Tricks wie man den Compiler dazu bringen kann Code zu generieren der die generischen Typinformationen in machen Situationen erhält.
Ein Trick ist beispielsweise einer Methode mit generischem Varargs (..., ellipse) Parameter und dem selben Rückgabetyp zu erstellen und diese Methode dann im Code aufzurufen. Der Java Compiler fasst dann die beim Methodenaufruf übergebenen Parameter zusammen, indem er mit Type Inferenz den Typ ermittelt welcher den übergebenen Parametern zugrundeliegt und anschließend ein Array vom dem Typ erzeugt.
Siehe Beispiel.
Beispiel:
Code java:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
package de.tutorials.training; import javax.swing.JButton; import javax.swing.table.DefaultTableModel; public class GenericTypeFactoryExample { public static void main(String[] args) { System.out.println(new Generic<Object>().create()); System.out.println(new Generic<DefaultTableModel>().create()); JButton button = create(); // Vom Java Compiler wird nun folgender Code erzeugt: //JButton button = create(new JButton[0]); //Durch Type Inference zum Rückgabetyp der create Methode wird der generische Parameter Typ auf JButton gesetzt //Hier ein Beispiel für die explizite Angabe des zu verwendenden Typs System.out.println(GenericTypeFactoryExample.<JButton>create()); //Vom Java Compiler wird nun folgender Code erzeugt: //JButton button = create(new JButton[0]); } public static <T> T create(T...ts){ try { return (T)ts.getClass().getComponentType().newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } static class Generic<T>{ @SuppressWarnings("unchecked") public T create(T...ts){ try { return (T)ts.getClass().getComponentType().newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } } }
Ausgabe:
Code :1 2 3
java.lang.Object@5d0385c1 javax.swing.table.DefaultTableModel@164f1d0d javax.swing.JButton[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.BorderUIResource$CompoundBorderUIResource@1cf11404,flags=296,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=2,left=14,bottom=2,right=14],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=true,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=,defaultCapable=true]
Gruß TomJava rocks!
How to become a good Java Programmer?
Does IT in Java and .Net
The only valid measurement of code quality: WTFs / minute
Blog
Xing
Twitter
-
Hallo Tom,
Besten Dank für deine Infos, das hat mich schon viel weiter gebracht! Allerdings habe ich jetzt noch ein Problem bezüglich Vererbung. Meine Klasse sieht folgendermassen aus:
Code java:1 2 3 4 5 6 7 8 9 10 11 12 13
public class ListenServer<T extends ClientSocket> { //... @SuppressWarnings("unchecked") private T createSocketWrapper(T...ts) { try { return (T)ts.getClass().getComponentType().newInstance(); } catch (Exception e) { System.out.println(ts.getClass().getComponentType().toString()); throw new java.lang.RuntimeException(e); } } //... }
In meinem Testprojekt habe ich dann folgende Versuchsklasse gemacht:
Code java:1 2 3 4 5 6
public class LogonClient extends ClientSocket { @Override protected void OnConnect() { System.out.println("Client connected: " + mClientSocket.toString()); } }
Entsprechend ist ClientSocket eine abstrakte Klasse. In der Verwendung sieht es folgendermassen aus:
Code java:1
ListenServer<LogonClient> listener = new ListenServer<LogonClient>();
Das Problem nun ist jetzt aber, dass in der Klasse createSocketWrapper Methode versucht wird eine Instanz der Klasse ClientSocket zu erstellen und nicht von LogonClient. Das schlägt natürlich (rückwirkend betrachtet zum Glück) fehl da ClientSocket abstrakt ist. Aber warum das?
Gruss
MuepeViele Tutorials und Artikel zur Programmierung unter Windows mit C++ und C#. Tägliche Updates und Antworten auf eure Fragen:
Win32Easy - Blog
Es würde mich freuen, wenn ihr einen Kommentar postet!
-
Nachdem ich mir das über Nacht mal bisschen durch den Kopf habe gehen lassen ist mir eigentlich auch klar geworden warum das obige Verhalten auftritt:
die createSocketWrapper Methode wird innerhalb der Klasse LogonClient aufgerufen und das generische vararg Element wird daher bereits beim Compilieren der Klasse LogonClient ausgefüllt. Zu diesem Zeitpunkt kennt der Compiler den finalen Typ LogonClient natürlich noch nicht und muss einen möglichst guten Treffer, der aber immer funktioniert für T finden. Das ist dann natürlich ClientSocket, da T sicher immer von ClientSocket erbt. Ich habe es nun so gemacht, dass der Konstruktor von LogonClient noch variable generische Parameter hat, die dann verwendet werden können.
Code java:1 2 3 4
public ListenServer(String addr, int port, T... ts) throws IOException { //... mGenericCreator = new Generic<T>(ts.getClass().getComponentType()); }
Wobei dann mGenericCreator eine Instanz der folgenden privaten Klasse ist:
Code java:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
private class Generic<S> { public Generic(Class<?> typeClass) { mTypeClass = typeClass; } @SuppressWarnings("unchecked") public S createSocketWrapper() { System.out.println(mTypeClass.toString()); try { return (S)mTypeClass.newInstance(); } catch (Exception e) { throw new java.lang.RuntimeException(e); } } private Class<?> mTypeClass; }
Damit funktioniert jetzt eigentlich alles so wie ich es möchte. Ist zwar ziemlich umständlich (leider, da ich als von C++ und C# kommender natürlich eine viel grössere Flexibilität von Generics gewohnt bin und mein Code exzessiven Gebrauch davon macht), aber am Ende zählt ja, dass es funktioniert
Gruss
MuepeViele Tutorials und Artikel zur Programmierung unter Windows mit C++ und C#. Tägliche Updates und Antworten auf eure Fragen:
Win32Easy - Blog
Es würde mich freuen, wenn ihr einen Kommentar postet!
Ähnliche Themen
-
Instanzieren von generischen Typen
Von xxsaikoxx im Forum JavaAntworten: 3Letzter Beitrag: 30.12.07, 11:14 -
Problem mit generischen klassen und methoden
Von MonsyX im Forum JavaAntworten: 11Letzter Beitrag: 23.10.07, 11:32 -
XSD-Problem mit gemeinsamen Typen
Von Eko im Forum XML TechnologienAntworten: 2Letzter Beitrag: 01.10.07, 19:48 -
Instanzen von mit internal markierten (generischen) Typen erstellen
Von Thomas Darimont im Forum .NET CaféAntworten: 0Letzter Beitrag: 27.03.07, 14:13 -
JNI Typen-Problem
Von kroesi im Forum JavaAntworten: 2Letzter Beitrag: 21.11.05, 12:57





Zitieren

Login





