Frage

Gibt es eine Möglichkeit, eine Methode mit Anmerkungen zu versehen, sodass alle ausgelösten Ausnahmen automatisch in Laufzeitausnahmen umgewandelt werden?

@MagicAnnotation
// no throws clause!
void foo()
{
  throw new Exception("bar")'
}
War es hilfreich?

Lösung

Auf keinen Fall zu tun, dass, zumindest für jetzt ich Abhilfe wie folgt verwenden (vereinfacht):

@SuppressWarnings({"rawtypes", "unchecked"})
public class Unchecked {
    public static interface UncheckedDefinitions{
        InputStream openStream();
        String readLine();
            ...
    }

  private static Class proxyClass = Proxy.getProxyClass(Unchecked.class.getClassLoader(), UncheckedDefinitions.class);

    public static UncheckedDefinitions unchecked(final Object target){
        try{
            return (UncheckedDefinitions) proxyClass.getConstructor(InvocationHandler.class).newInstance(new InvocationHandler(){
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    if (target instanceof Class){
                        return MethodUtils.invokeExactStaticMethod((Class) target, method.getName(), args);
                    }

                  return MethodUtils.invokeExactMethod(target, method.getName(), args);
                }
            });
        }
        catch(Exception e){
            throw new RuntimeException(e);
        }
    }
}

Und die Nutzung wie folgt aussieht:

import static ....Unchecked.*;

...

Writer w = ...;
unchecked(w).write(str, off, len);

Der Trick ist, dass Schnittstelle ist „nie fertig“ und jedes Mal muss ich irgendwo unkontrolliert Methode, ich werde wickeln das Objekt in nicht markiert und lassen IDE Methodensignatur in der Schnittstelle erzeugen.

Die Umsetzung ist dann generisch (reflektierende und „langsam“, aber in der Regel schnell genug)

Es gibt einige Code Postprozessoren und Bytecode-Weber aber das war nicht möglich (auch nicht aop oder andere Jvm basierte Sprache) für ein aktuelles Projekt, so wurde dieser „erfunden“.

Andere Tipps

Projekt Lombok @SneakyThrows ist wahrscheinlich das, was Sie suchen. Ist das nicht wirklich Ihre Ausnahme Einwickeln (weil es ein Problem in vielen Fällen sein kann), es funktioniert einfach nicht einen Fehler bei der Kompilierung werfen.

@SneakyThrows
void foo() {
    throw new Exception("bar")'
}

Sie können dies mit AspectJ tun.Sie deklarieren einen Joinpoint (in diesem Fall Aufruf der Methode foo) und „mildern“ die Ausnahme.

Bearbeiten Um dies etwas näher zu erläutern:

Angenommen, Sie haben die folgende Klasse Bar:

public class Bar {

    public void foo() throws Exception {
    }
}

...und Sie haben einen Test wie diesen:

import junit.framework.TestCase;

public class BarTest extends TestCase {

    public void testTestFoo() {
        new Bar().foo();
    }
}

Dann lässt sich der Test offensichtlich nicht kompilieren.Es wird ein Fehler ausgegeben:

Unhandled exception type Exception  BarTest.java(line 6)

Um dies nun mit AspectJ zu überwinden, schreiben Sie einen sehr einfachen Aspekt:

public aspect SoftenExceptionsInTestCode {

    pointcut inTestCode() : execution(void *Test.test*());

    declare soft : Exception : inTestCode();
}

Der Aspekt besagt im Grunde, dass jeder Code aus einem Test (d. h.:Eine Methode, die mit „test“ in einer Klasse beginnt, die mit „Test“ endet und „void“ zurückgibt), die eine Ausnahme auslöst, sollte vom AspectJ-Compiler akzeptiert werden.Wenn eine Ausnahme auftritt, wird sie umschlossen und als ausgelöst RuntimeException durch den AspectJ-Compiler.

Wenn Sie diesen Test als Teil eines AspectJ-Projekts in Eclipse ausführen (mit installiertem AJDT), ist der Test tatsächlich erfolgreich, während er ohne den Aspekt nicht einmal kompiliert werden kann.

Ich denke, es ist möglich, mit Bytecode Re-Engineering, kundenspezifische Compiler oder vielleicht aspektorientierte Programmierung 1 . Im Gegensatz zu Java, C # hat nur ungeprüfte Ausnahmen 2 .

Darf ich fragen, warum Sie die geprüfte Ausnahmen zu unterdrücken wollen?

1 nach Maarten Winkel dies möglich ist.
2 und sie über die Einführung geprüft diejenigen denken, einige Channel 9 Videos nach.

Edit: Für die Frage: Es ist möglich, in dem Sinne, dass Sie Ihre Methoden Flagge mit Anmerkungen versehen können sie ein Kandidat für die geprüfte Ausnahme Unterdrückung zu sein. Dann Sie einige der Kompilierung oder zur Laufzeit Trick verwenden, um die tatsächliche Unterdrückung / Verpackung anzuwenden.

Wie ich jedoch die Umgebung um Ihren Fall nicht sehen, eine Ausnahme in dieser Hinsicht Einwickeln könnte die Kunden dieser Methode verwirren - sie könnten nicht mit einem Runtime beschäftigen werden vorbereitet. Zum Beispiel: wirft die Methode eine IOException und Ihre Kunden fängt es als FileNotFoundException einen Fehlerdialog angezeigt werden soll. Allerdings, wenn Sie Ihre Ausnahme in eine Runtime wickeln, wird der Fehlerdialog niemals angezeigt und wahrscheinlich tötet es den Anrufer Thread zu. (IMHO).

Die Checked Ausnahmen sind keinerlei Gewährleistung der Verfahrensführung. Nehmen Sie sehr, sehr sorgfältig diese Tatsache. wenn Sie Artefakte nicht wie die Verwendung umgehen können.

Sie können dies von der Tatsache, über die Verwendung in jedem Fall tun, dass Class.newInstance nicht ein Exception durch den nicht-arg Konstruktor in einem InvocationTargetException geworfen wickeln; sie wirft es eher leise :

class ExUtil {
  public static void throwSilent(Exception e) { //NOTICE NO THROWS CLAUSE
      tl.set(e);
      SilentThrower.class.newInstance(); //throws silently
  }

  private static ThreadLocal<Exception> tl = new ThreadLocal<Exception>();
  private static class SilentThrower {
      SilentThrower() throws Exception {
          Exception e = tl.get();
          tl.remove();
          throw e;
      }
  }
}

Dann können Sie dieses Dienstprogramm verwenden, überall:

ExUtil.throwSilent(new Exception());
//or
try {
  ioMethod();
} catch (IOException e) { ExUtil.throwSilent(e); }

By the way, das ist eine wirklich schlechte Idee : -)

Ich verwende die Fertigstellung / Template-System von Eclipse leicht jeden Codeblock zu wickeln.

Hier ist meine Vorlage:

try { // Wrapp exceptions

${line_selection}${cursor}

} catch (RuntimeException e) { // Forward runtime exception
throw e;
} catch (Exception e) { // Wrap into runtime exception
throw new RuntimeException(
    "Exception wrapped in #${enclosing_method}", 
    e); 
}

Mit Java 8 es ist so einfach wie: soften(() -> methodThatMayThrow())

Lesen Sie mehr unter http: //iirekm.blogspot .com / 2014/05 / fix-Probleme-mit-java-checked.html

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top