Die meisten Skriptsprachen (wie Perl) und nicht statischen Sprachen zur Kompilierungszeit (wie Pick) unterstützen automatische dynamische Konvertierungen von Zeichenfolgen in (relativ willkürliche) Objekte zur Laufzeit. Dies kann auch in Java erreicht werden, ohne die Typensicherheit zu verlieren, und die guten statisch typisierten Sprachen bieten OHNE die bösen Nebenwirkungen einiger anderer Sprachen, die mit dynamischem Casting böse Dinge tun. Ein Perl-Beispiel, das fragwürdige Berechnungen anstellt:
print ++($foo = '99'); # prints '100'
print ++($foo = 'a0'); # prints 'a1'
In Java wird dies besser erreicht (IMHO), indem eine Methode verwendet wird, die ich "Cross-Casting" nenne. Beim Cross-Casting wird die Reflexion in einem verzögert geladenen Cache von Konstruktoren und Methoden verwendet, die mithilfe der folgenden statischen Methode dynamisch erkannt werden:
Object fromString (String value, Class targetClass)
Leider tun dies keine integrierten Java-Methoden wie Class.cast () für String to BigDecimal oder String to Integer oder andere Konvertierungen, bei denen keine unterstützende Klassenhierarchie vorhanden ist. Für meinen Teil geht es darum, einen vollständig dynamischen Weg zu finden, um dies zu erreichen - für den ich nicht denke, dass die vorherige Referenz der richtige Ansatz ist - und jede Konvertierung codieren zu müssen. Einfach ausgedrückt, die Implementierung ist nur aus dem String zu werfen, wenn es legal / möglich ist.
Die Lösung ist also eine einfache Reflexion, bei der nach öffentlichen Mitgliedern gesucht wird:
STRING_CLASS_ARRAY = (neue Klasse [] {String.class});
a) Mitglied member = targetClass.getMethod (method.getName (), STRING_CLASS_ARRAY); b) Mitglied member = targetClass.getConstructor (STRING_CLASS_ARRAY);
Sie werden feststellen, dass alle Grundelemente (Integer, Long usw.) und alle Grundlagen (BigInteger, BigDecimal usw.) und sogar java.regex.Pattern über diesen Ansatz abgedeckt werden. Ich habe dies mit großem Erfolg bei Produktionsprojekten verwendet, bei denen es eine große Anzahl beliebiger String-Werteingaben gibt, bei denen eine strengere Überprüfung erforderlich war. Wenn bei diesem Ansatz keine Methode vorhanden ist oder wenn die Methode aufgerufen wird, wird eine Ausnahme ausgelöst (da es sich um einen unzulässigen Wert handelt, z. B. eine nicht numerische Eingabe in ein BigDecimal oder eine unzulässige RegEx für ein Muster), die die Prüfung für bereitstellt die inhärente Logik der Zielklasse.
Dies hat einige Nachteile:
1) Sie müssen die Reflexion gut verstehen (dies ist etwas kompliziert und nicht für Anfänger). 2) Einige der Java-Klassen und Bibliotheken von Drittanbietern sind (überraschenderweise) nicht richtig codiert. Das heißt, es gibt Methoden, die ein einzelnes Zeichenfolgenargument als Eingabe verwenden und eine Instanz der Zielklasse zurückgeben, aber es ist nicht das, was Sie denken ... Betrachten Sie die Integer-Klasse:
static Integer getInteger(String nm)
Determines the integer value of the system property with the specified name.
Die obige Methode hat wirklich nichts mit Ganzzahlen als Objekten zu tun, die primitive Ints umschließen. Reflection wird dies als einen möglichen Kandidaten für das falsche Erstellen einer Ganzzahl aus einem String im Vergleich zu den Dekodierungs-, Wert- und Konstruktorelementen finden. Diese sind alle für die meisten willkürlichen String-Konvertierungen geeignet, bei denen Sie wirklich keine Kontrolle über Ihre Eingabedaten haben, sondern nur möchten wissen, ob es möglich ist, eine Ganzzahl.
Um Abhilfe zu schaffen, ist die Suche nach Methoden, die Ausnahmen auslösen, ein guter Anfang, da ungültige Eingabewerte, die Instanzen solcher Objekte erstellen, dies tun sollten , eine Ausnahme . Leider variieren die Implementierungen dahingehend, ob die Ausnahmen als aktiviert deklariert sind oder nicht. Integer.valueOf (String) löst beispielsweise eine überprüfte NumberFormatException aus, aber Pattern.compile () -Ausnahmen werden bei Reflection-Lookups nicht gefunden. Auch hier ist ein Fehlschlagen dieses dynamischen "Cross-Casting" -Ansatzes meiner Meinung nach keine sehr standardmäßige Implementierung für Ausnahmedeklarationen in Objekterstellungsmethoden.
Wenn jemand mehr Details darüber möchte, wie das oben Genannte implementiert wurde, lassen Sie es mich wissen, aber ich denke, diese Lösung ist viel flexibler / erweiterbarer und mit weniger Code, ohne die guten Teile der Typensicherheit zu verlieren. Natürlich ist es immer am besten, "Ihre Daten zu kennen", aber wie viele von uns feststellen, sind wir manchmal nur Empfänger von nicht verwalteten Inhalten und müssen unser Bestes tun, um sie richtig zu verwenden.
Prost.