PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Java Wrapper Klassen & Annotationen


#44
2008-06-04, 08:32:57
Ich habe ein Problem mit einem TableModel.
Dieses gibt für jede Spalte die .class des darzustellenden Typs mittels einer Methode an die Table, allerdings kommt bei primitiven (int.class) eine Exception, weil der Wrapperklassentyp erwartet wird (Integer.class).

Mein Problem besteht deshalb, weil erst zur Laufzeit bekannt ist welcher Typ dargestellt werden soll.

Momentan löse ich das so:

private Class primitiveToWrapper(Class target)
{
if (target.isPrimitive())
{
if (target == boolean.class)
target = Boolean.class;
else
if (target == int.class)
target = Integer.class;
else
if (target == double.class)
target = Double.class;
else
if (target == byte.class)
target = Byte.class;
else
if (target == float.class)
target = Float.class;
else
if (target == long.class)
target = Long.class;
else
if (target == char.class)
target = Character.class;
else
if (target == short.class)
target = Short.class;
}
return target;
}

Prinzipiell könnte man das auch mit einer Hash-Map stark verkürzen, mich interessiert aber eher ob Java da eine Funktion bereitstellt.

€: Ausserdem wüsste ich gern ob Java-Annotationen wirlich so beschränkt sind. Ich habe bis jetzt keine Möglichkeite gefunden Annotationen auf Methoden/Felder die bestimmte Vorraussetzungen erfüllen (public, nicht void) einzuschränken. Gibt es da Möglichkeiten/Workarounds? Das während der Laufzeit auszuwerten will mir nicht recht gefallen...

Trap
2008-06-04, 11:48:05
Würde primitive per cast/autoboxing in Objekte wandeln und dann .class nachgucken nicht auch funktionieren?

Ganon
2008-06-04, 12:38:01
Jup, das sollte gehen:


int test = 10;
Object obj = test;
System.out.println(obj.getClass());

class java.lang.Integer

#44
2008-06-04, 13:32:30
Dummerweise nutzt mein Programm Reflection und Ich bekomme die Klasse per (vereinfacht; der Check ob die Annotation (s.u.) vorhanden ist, hab ich mal weggelassen)
MeineKlasse.class.getMethods()[i].getReturnType()
was wiederum int.class etc. liefert.

Und habe zu der Zeit noch kein Objekt der Klasse um die Methode zu invoken und so eine Instanz des Return-Typs zu bekommen.

€: Um das Bild zu vervollständigen: Mein TableModel akzeptiert beliebige Klassen von welcher es Instanzen in einer Table darstellt. Die Werte, welche in der Tabelle dargestellt werden sollen, müssen mit einer Annotation versehen werden (= Ich weiss erst zur Laufzeit wieviele und welche Methoden aufgerufen werdem müssen um die Tabelle zu füllen, und von welchem Typ die Spalten sind)
All das läuft im Konstruktor des Models ab, dem der Klassentyp der darzustellenden Objekte übergeben wird (Ich speichere die Klassentypen in einem Array um nicht ständig die Methoden zur Klassenbestimmung rufen zu müssen).

Meine Lösung sieht mittlerweile so aus:

private static final HashMap<Class, Class> classMap = getInitialClassMap();

public static Class primitiveToWrapper(Class target)
{
if (target.isPrimitive())
{
target = classMap.get(target);
}
return target;
}
private static HashMap<Class, Class> getInitialClassMap()
{
HashMap<Class, Class> returnValue = new HashMap<Class, Class>();
returnValue.put(boolean.class, Boolean.class);
returnValue.put(byte.class, Byte.class);
returnValue.put(char.class, Character.class);
returnValue.put(double.class, Double.class);
returnValue.put(float.class, Float.class);
returnValue.put(int.class, Integer.class);
returnValue.put(long.class, Long.class);
returnValue.put(short.class, Short.class);

return returnValue;
}

Shink
2008-06-04, 14:14:52
Tja, bei solchen Schweinereien würd ich dann doch die HashMap-Variante wählen. Was du machst ist ja ohnehin irgendwie... hmmm...

Ganon
2008-06-04, 14:17:56
Tja, bei solchen Schweinereien würd ich dann doch die HashMap-Variante wählen. Was du machst ist ja ohnehin irgendwie... hmmm...

Was ist denn daran so schlimm? Also die herangehensweise?

Coda
2008-06-04, 19:21:46
Hat zwar nichts mit dem Thema zu tun, aber warum schreibst du die "else if" so hin und nicht untereinander? :|

Shink
2008-06-04, 20:27:37
Was ist denn daran so schlimm? Also die herangehensweise?
Naja... ich finde halt wenn man da (woher auch immer die kommen mögen) primitive Datentypen reinziehen kann, warum macht man dann Sachen mit der Klasse die man nicht mit primitiven Datentypen machen kann?

Und wenn man Sachen macht, die nur mit Objects gehen, was will man dann mit primitiven Datentypen machen?

So oder so geht der eigentliche Typ verloren. Das mag für manche Zwecke in Ordnung sein, aber wenn man schon etwas nicht allgemein gültiges macht muss man IMO nicht erwarten dass die Programmiersprache/Bibliothek etwas zur Verfügung stellt, was einem das abnimmt.
Ich hoffe es ist ungefähr klar was ich damit meine.

Ganon
2008-06-04, 21:01:31
Achso. Ich dachte du meinst jetzt allgemein das Tabellenmodell, welches halt dynamisch, anhand von Annotations, zusammengestellt wird.

Weil etwas ähnlich habe ich nämlich auch vor. :D Ich habe aber auch noch nicht die große Erfahrung in Java-Programmierung, daher meine Frage ^_^

#44
2008-06-05, 10:14:30
Hat zwar nichts mit dem Thema zu tun, aber warum schreibst du die "else if" so hin und nicht untereinander? :|

Weil das das Einzige ist, von dem ich keine Ahnung habe wie ich es der Eclipse-Autoformatierung abgewöhnen kann. :/

Naja... ich finde halt wenn man da (woher auch immer die kommen mögen) primitive Datentypen reinziehen kann, warum macht man dann Sachen mit der Klasse die man nicht mit primitiven Datentypen machen kann?

Und wenn man Sachen macht, die nur mit Objects gehen, was will man dann mit primitiven Datentypen machen?
Die Table muss ja die richtigen CellRenderer und CellEditoren für die Spalte kennen, die holt sie über die Klasse der Objekte die in der Spalte dargestellt werden. Wenn ich nun primitive darstellen will muss ich zwangsweise die Klasse des Wrappertyps angeben...

Bin mir aber grad nicht sicher ob ich deinen Post verstehe.

Shink
2008-06-05, 10:31:00
Weil das das Einzige ist, von dem ich keine Ahnung habe wie ich es der Eclipse-Autoformatierung abgewöhnen kann. :/
Wenn du "else if" statt "else \n if" schreibst schreibt er das untereinander. Irgendwie macht das auch Sinn.


Die Table muss ja die richtigen CellRenderer und CellEditoren für die Spalte kennen, die holt sie über die Klasse der Objekte die in der Spalte dargestellt werden. Wenn ich nun primitive darstellen will muss ich zwangsweise die Klasse des Wrappertyps angeben...

Bin mir aber grad nicht sicher ob ich deinen Post verstehe.
Wahrscheinlich versteh ich ja auch das eigentliche Problem nicht.
Wo genau geschieht bei Verwendung von primitiven Typen eine Exception?

#44
2008-06-05, 10:56:49
Wenn du "else if" statt "else \n if" schreibst schreibt er das untereinander. Irgendwie macht das auch Sinn.
"Keep else if on one line" in den Autoformatter-Optionen. Danke!

Wahrscheinlich versteh ich ja auch das eigentliche Problem nicht.
Wo genau geschieht bei Verwendung von primitiven Typen eine Exception?
Nun wie gesagt, ich habe ein TableModel gebastelt mit dem man beliebige Objekte darstellen kann, in deren Klassendeklaration Methoden mit Returntyp mit einer speziellen Annotation versehen wurde. Diese Methoden werden für die darzustellenden Objekte aufgerufen und die Ergebnisse in einer Spalte je Methode dargestellt.

Wenn jetzt der Rückgabewerte der Methode int ist soll natürlich eine Spalte mit Zahlen dargestellt werden. Momentan hole Ich mir per
DarzustellendeKlasse.class.getMethods()[i].getReturnType()
die Klasse der Rückgabewerte. Da kommt dann natürlich int.class zurück, falls der Rückgabewert int ist.
JTable bringt "Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at javax.swing.JTable.prepareRenderer(Unknown Source)" sobald soetwas passiert.

Evtl mache ich auch generell was mit dem JTable falsch.

Shink
2008-06-05, 11:13:21
Hmm.. ich weiß ich könnts selbst nachbauen aber... könntest du mir bitte JRE-Version sagen und das Zeug so compilieren dass du die Zeilennummern im Stacktrace siehst (ist ne Compileroption; heißt Debug o.ä.)?
Ich versteh nicht ganz was man bei int.class eine NEX liefert und bei Integer.class nicht.

#44
2008-06-05, 11:29:08
Ich versteh nicht ganz was man bei int.class eine NEX liefert und bei Integer.class nicht. Ich könnte mir vorstellen das es für int.class keinen TableCellRenderer gibt, denn prepareRenderer will u.a. einen Renderer als Argument...

JRE: 1.6.0_04
Die Zeilennummer werden bei meinen eigenen Klassen schon angezeigt, bei internen garnicht (Keine Zeilennummer einkomiliert?; Evtl mit den Java-Sourcen?). Hab bis jetzt die Option noch nicht gefunden.

Shink
2008-06-05, 11:37:59
JRE: 1.6.0_04
Die Zeilennummer werden bei meinen eigenen Klassen schon angezeigt, bei internen garnicht (Keine Zeilennummer einkomiliert?; Evtl mit den Java-Sourcen?). Hab bis jetzt die Option noch nicht gefunden.
Stell mal die JRE einer JDK ein. Dann kannst du auch selbst dort herumsuchen.