"dynamic cast" unter Java
-
Bei den Dateinamen ist es noch viel schrecklicher!
Gibt es noch einen anderen Weg? Die schrecklichen Klassennamen sind generierter Code. An die Stylesheets für die Code-Generierung möchte ich nur sehr ungern gehen. Richtig "arbeiten" kann ich nur in den Klassen ohne den Zusatz "impl", da hier nichts mehr nachkommen kann.
Was bedeutet "Downcast". Ich komme aus der C++-Ecke und da ist ein downcast eigentlich genau der umgekehrte Fall. Im Übrigen: Ich muss (derzeit) noch mit 1.3.1 arbeiten!
-
Hi
eine möglichkeit ist sach ich mal die mit der brechstange. einfach kasten und gucken was zur laufzeit passiert. wenns knallt fehler fangen und ausnahmebehandlung machen. wozu hat java den eine CastException und Try catch?
andere weg währe vorher zu prühfen, ob die classe das Interface implementiert oder von der klasse abgeleitet ist. Object.getClass().isInstance() oder sowas.
schau dir mal class etwas genauer an.
http://java.sun.com/j2se/1.3/docs/api/java/lang/Class.htmlgruss
-
Danke an alle für die schnellen Antworten.
Lösung 1:
public void createAddJS (PrintWriter _out, String _target, boolean _error) { logDebug(m_Module.getIISession().getLogId() + "createAddJS for " + getParentUnit().getUnitName()); IIUnitLogic1500_unit_ICFDyn unit = (IIUnitLogic1500_unit_ICFDyn) getParentUnit(); try { if (unit.m_interpreter != null) unit.m_interpreter.draw_js(_out); } catch ( Exception ex ) { catchIIError ( ex ) ; } }
Eher schlecht, da nicht unbedingt die unit_ICFDyn die parent-Unit sein muss.
Lösung 2:
public void createAddElem (PrintWriter _out, String _target, boolean _error) { logDebug(m_Module.getIISession().getLogId() + "createAddElem for " + getParentUnit().getUnitName()); //Klasse prüfen boolean interpreter_avail = false; Object f = null; Class _class = getParentUnit().getClass(); try { f = (Object) _class.getField ("m_interpreter"); interpreter_avail = true; } catch (Exception NoSuchFieldException) { interpreter_avail = false; } //Aufruf der Draw-Funktion in m_interpreter if (interpreter_avail && (f != null)) { com.i7business.IIModule1500.CMDInterpreter interpreter = (com.i7business.IIModule1500.CMDInterpreter) f; interpreter.draw (_out); } }
Diese setzt nur noch das Vorhandensein von m_interpreter voraus, was innerhalb dieses Moduls jedoch sicher ist.
Da fühle ich mich schon fast wieder zu-c++-Hause. Casten bis der Arzt kommt!
Kann man da noch was verbessern?
-
Hi
zu teil ein würd ich den cast, den du etws problematisch ansiest in einen try catch block packen wegen der sicherheit.
kurtze frage tut das auch so ich mein teil 2 auch? getField() liefert ein Field object der Reflection api. das ist nur ein Obj das ein feld inerhalb einer klasse beschreibt. somit kein Object. erst mit Field.get() bekomst du das wahre Feld des übergebenen Objektes.
public void createAddElem (PrintWriter _out, String _target, boolean _error) { logDebug(m_Module.getIISession().getLogId() + "createAddElem for " + getParentUnit().getUnitName()); //Klasse prüfen boolean interpreter_avail = false; Object obj = getParentUnit(); // << Field f = null; // << Class _class = obj.getClass(); // << try { f = _class.getField ("m_interpreter"); // << interpreter_avail = true; } catch (Exception NoSuchFieldException) { interpreter_avail = false; } //Aufruf der Draw-Funktion in m_interpreter if (interpreter_avail && (f != null)) { com.i7business.IIModule1500.CMDInterpreter interpreter = (com.i7business.IIModule1500.CMDInterpreter) f.get(obj); // << // ggf sicherstellen, das das feld auch von dem typ ist auf das du es castest. interpreter.draw (_out); } }
ich hoff das ich da jetzt keine fehler reingebracht hab.
[Edit]
Achtung. die Reflection Api ist nicht gerade die schnellste.
gruss Termite
-
Soweit war ich schon. Jedoch lehnt der Compiler einen direkten cast von Field nach CMDInterpreter ab. Exceptions werden schon von außerhalb abgefangen. Wenn das fehlschlägt, kann ich mit dem gelieferten Krempel ohnehin nix anfangen.
Leider schlägt es fehl. Der cast von (Object) Field nach CMDInterpreter wird zwar kompiliert, führt jedoch zur ClassCastException.
Dumme Sache das.
-
Es gibt auch noch den instanceof Operator:
MyClass blah; if (myObject instanceof MyClass) { blah = (MyClass)myObject; // Cast ist hier sicher. }
-
Termite schrieb:
wozu hat java den eine CastException und Try catch?
Das ist ganz ganz böse. Eine ClassCastException ist eine RuntimeException. Generell kann man zu allen RuntimeExceptions sagen, dass ein Programmierfehler vorliegt, wenn eine ausgelöst wird. Die sollte man nicht fangen, sonst fällt am Schluss noch überhaupt nicht auf, dass das Programm fehlerhaft ist oder es ist schwerer, herauszufinden, warum das Programm nicht funktioniert.
...und da ich das hier auch gesehen habe: Exceptions allgemein fangen ist noch viel schlimmer. Komplett unwartbarer und hoch fehleranfälliger Code.
-
"instanceof" scheint wohl das zu sein, was ich gesucht habe. Danke.
Gregor@Home schrieb:
...und da ich das hier auch gesehen habe: Exceptions allgemein fangen ist noch viel schlimmer. Komplett unwartbarer und hoch fehleranfälliger Code.
Falls Du das hier meinst:
catch ( Exception ex ) { catchIIError ( ex ) ; }
Da erhalte ich Romane, die ich nicht mal unter einem Debugger erhalten würde. Im Gegensatz zu C++ erhalte ich nicht nur die Adresse der catch-Zeile und kann dann suchen, wo in den vorhergehenden 50 Zeilen die exception ausgelöst wurde, sondern erhalte generell die gesamte Aufrufliste mit allen Parametern. catchIIError hab ich nicht programmiert, ist aber halt einfach so da.
Würden exceptions einfach so abgefangen, damit in der Hauptsache das Programm weiterläuft, wäre das wirklich ziemlich fatal. In diesem speziellen Fall wäre die ganze Funktionalität an dieser Stelle ohne ein "m_interpreter" allerdings ziemlich sinnfrei. Zumindest ein Eintrag in der Log-Datei wäre jedoch angebracht.
-
Manfred Schmidtke schrieb:
Was bedeutet "Downcast". Ich komme aus der C++-Ecke und da ist ein downcast eigentlich genau der umgekehrte Fall. Im Übrigen: Ich muss (derzeit) noch mit 1.3.1 arbeiten!
Ein Downcast ist auch in C++ ein Cast nach unten in der Hierarchie. Die Basisklasse steht ganz oben und alle anderen hängen unten dran. In der Informatik wachsen Bäume immer nach unten.
-
Da habe ich den nicht gerade umfangreichen Text zu DYNAMIC_DOWNCAST wohl komplett mißverstanden. Meine dolle Bibliothek (oder was davon übrig ist) schweigt zu dem Thema ganz und das Netz gibt dazu auch nicht viel her.
So lernt man halt nie aus!