Ich stieß auf einen interessanten Code in java.lang.Class # newInstance0:
%Vor% Überprüfen Sie die Unsafe.getUnsafe().throwException
-Anweisung. Es sieht so aus, als ob eine geprüfte Ausnahme von einer Methode ausgelöst wird, die sie nicht als geworfen deklariert!
Warum haben sie das gemacht?
Wenn die Sun-Entwickler diese Technik anwenden können, ist es auch für uns in Ordnung, dies zu tun?
Warum haben sie das gemacht?
Ich bin mir nicht ganz sicher, aber ich nehme an, dass es einen wirklich guten Grund gab. (Wenn Sie einen Drilldown durch die Ebenen ausführen, beinhaltet der reflektierende Aufruf einige äußerst knifflige Dinge ...)
Wenn die Sun-Entwickler diese Technik verwenden können, ist es auch für uns in Ordnung, dies zu tun?
Ich würde nein sagen ... außer du hast einen wirklich guten Grund. Methoden, die geprüfte Ausnahmen auslösen, ohne sie zu deklarieren, verstoßen gegen das Prinzip der geringsten Überraschung. Denken Sie an den armen Kerl, der Ihren Code in einem kritischen Produktionssystem um 3 Uhr morgens debuggen müsste.
Nur weil ein Sun-Ingenieur entschieden hat, dass etwas in einem bestimmten Kontext eine gute Idee ist, macht es das im Allgemeinen nicht immer zu einer guten Idee.
Mit Java und Generika können Sie von der Art des Löschens profitieren und einfach jede Ausnahme mit diesem einfachen Trick auslösen:
%Vor%Schrecklich, aber ...
Es gibt einen interessanten Blog auf Vermeiden von Checked Exeptions von Don Schwarz. Danke für das Teilen.
Das Problem bei der Verwendung der Klasse Unsafe besteht darin, dass es nur für den internen Gebrauch bestimmt ist und keine definierte Schnittstelle und IS für verschiedene Plattformen aufweist.
Mit Standardaufrufen können Sie das Gleiche erreichen. (Obwohl veraltet)
%Vor% Sun hat apparent dazu beigetragen, dass überprüfte Ausnahmen direkt aus Class.newInstance()
geworfen werden, anstatt entweder in InvocationTargetException eingeschlossen zu werden oder throws Exception
für die Signatur deklariert zu haben.
Dies ist eine "interessante" Designentscheidung, da sie sich von anderen Mustern unterscheidet - Constructor.newInstance () umschließt zum Beispiel alle Konstruktorausnahmen in einer InvocationTargetException.
Der "Vorteil", den es angeblich bietet, ist:
die Möglichkeit, Konstruktorausnahmen direkt mit ihrem ursprünglichen Typ abzufangen; und
verhindert, dass newInstance () throws Exception
deklariert und der Aufrufer Exception abfängt.
Der Nachteil ist:
Wäre das ein Muster, das Sie in Ihrem Code verwenden könnten? Das erscheint mir ziemlich unwahrscheinlich. Es scheint hauptsächlich potenziell auf generischen / Framework-Code anwendbar zu sein, bei dem Client-Code, der vom Framework umschlossen wird, möglicherweise geprüfte Ausnahmen auslöst. Dann wäre es nur wünschenswert zu verwenden, wenn Sie ausgecheckte Ausnahmen verbreiten möchten, ohne zu deklarieren, dass sie geworfen werden können. Für mich ist das fraglich.
Die meisten Java-Framework-Methoden, die Client-Code umschließen, sind in einem von drei Ausnahmeparadigmen entworfen:
throws Exception
, um den gesamten Gamut der geprüften Ausnahmen zuzulassen, oder Diese spezielle Class.newInstance
-Methode ist sehr ungewöhnlich, und indem sie die geprüften Ausnahmen nicht deklariert, die möglicherweise geworfen werden können, umgeht / vermeidet sie den einzigen wirklichen Vorteil der geprüften Ausnahmen.
Im Allgemeinen gab es eine große Verschiebung hin zur Laufzeit statt zu checked Ausnahmen, und ich würde Unsafe.throwException()
nicht empfehlen (und auch nicht den "Generics Hack", den Lukas oben erwähnt hat.)
Für Anwendungscode würde ich empfehlen, Laufzeitausnahmen zu verwenden, wenn möglich & amp; Deklarieren Sie die ausgelösten Ausnahmearten. Betrachten Sie für Framework-Code die drei obigen Paradigmen mit einer Präferenz für Laufzeitausnahmen.
Hintergrund: Ссылка