2009-06-30 11 views
0

Wie kann ich von Java anonyme Klassen ausgegeben werden? In .Net würde ich Schließungen verwenden.Ausgabe von anonymen Klassen?

executor = Executors.newSingleThreadExecutor(); 
final Runnable runnable = new Runnable() { 
    public Exception exception; 

    @Override 
    public void run() { 
    try { 
     doSomething(); 
    } 
    catch (Exception exception) { 
     // I'd like to report this exception, but how? 
     // the exception member is not readable from outside the class (without reflection...) 
     this.exception = exception; 
    } 
    } 
}; 

executor.submit(runnable); 

// Here I'd like to check if there was an exception 

Antwort

7

Die Executor Schnittstelle bietet keine Möglichkeit, dies zu tun. Wenn Sie jedoch newSingleThreadExecutor() aufrufen, erhalten Sie eine ExecutorService, die Funktionalität dafür enthält.

Der Aufruf ExecutorService.submit() gibt eine Instanz von Future<?> zurück, mit der Sie den Ergebniswert der Berechnung abrufen können.

Wenn die Ausführung zu einer Ausnahme geführt hat, wird durch Aufruf von get ein ExecutionException ausgelöst.

+0

Also sollte ich nicht Runnable verwenden, oder? – ripper234

+0

Wenn Sie ein Ergebnis erhalten möchten, sollten Sie Callable verwenden. Es gibt keine Möglichkeit, einen Wert als Ergebnis von Runnable zurückgeben (IIRC Aufruf 'Get' für Runnables Null zurückgegeben) – andri

+0

Vielmehr die Aufgabe, die ich ordnungsgemäß ausführen möchte keinen Rückgabewert, aber ich möchte auf Ausnahmen benachrichtigt werden. Runnable.run() deklariert keine Ausnahmen, daher kann ich das nicht verwenden. Callable muss etwas zurückgeben. Ich kann die aufrufbare Rückgabe die Ausnahme haben, aber das scheint ein bisschen suboptimal. Idealerweise hätte ich gerne eine andere ähnliche Klasse, deren 'run equivalent' Ausnahmen auslösen kann, aber void zurückgibt. Naja. – ripper234

-2

Wenn Sie die Ausnahme als endgültig definieren, kann die anonyme Klasse den Wert dort speichern und Sie können die Variable überprüfen, wenn run() ausgeführt wurde.

Bearbeiten zum Hinzufügen: Sorry, ich wollte es zu einem endgültigen Array von einer Ausnahme machen. Idee macht das automatisch für mich, deshalb vergesse ich oft die zusätzliche Umleitung.

final Exception[] except;

+0

Ich glaube nicht, dass das korrekt ist; Wenn Sie die Ausnahme als endgültig definieren, können Sie die Ausnahme nicht von der run() -Methode der Klasse aktualisieren (da Sie die endgültigen Verweise nicht ändern können). – Adamski

2

Um eine Ausnahme von einer Task auf einem Testamentsvollstrecker Sie Callable statt Runnable verwenden möchten zu erhalten.

Die call() - Methode von Callable kann geprüfte Ausnahmen auslösen. Wenn Sie get() auf Ihrer Future-Instanz aufrufen, wird eine ExecutionException ausgelöst, wenn Ihre call() -Methode eine geprüfte Ausnahme auslöst. Sie können dann auf die zugrunde liegende geprüfte Ausnahme zugreifen, indem Sie getCause() für die ExecutionException aufrufen.

+0

Diese Antwort ist Bang-On; Andere Antworten, die Hacky-Lösungen mit Runnable bereitstellen, sollten ignoriert werden. Das Standard-Idiom für diese Art von Problem ist Callable, nicht Runnable. – Adamski

+0

+1; Dafür wurde Callable erfunden. –

+0

Callable ist für die Ausgabe, also, wenn Sie die Ausnahme in einen Rückgabewert konvertieren möchten, der Fehler angibt, den Punkt der Ausnahmen an erster Stelle zu besiegen, dann ist Callable geeignet. Oder verwenden Sie einfach die Mechanismen, die in der Bibliothek angegeben sind - setzen Sie ein Runnable ein, geben Sie ein Future zurück, und holen Sie den Wert erneut, um die Ausnahme zu wiederholen. –

0

hackish .... aber, könnte man eine statische Variable/Methode, die die Runnable die Ausnahme zu berichten, rufen

public class Driver { 
static Exception exec; 
static final Runnable runnable = new Runnable() { 
    public Exception exception; 

    public void run() { 
     try { 
      throw new Exception("asdf"); 
     } 
     catch (Exception exception) { 
      exec = exception; 
     } 
    } 
    }; 

public static void main(String[] args) throws Exception{ 
    ExecutorService e = Executors.newSingleThreadExecutor(); 
    e.submit(runnable); 
    e.shutdown(); 
    while(e.isShutdown()==false){ 
     Thread.sleep(2000); 
    } 
    System.out.println(exec); 

} 
0

Sie könnten Ihre geworfen Ausnahme in einem Runtime wickeln und legen Sie Ihren executor.submit() Anruf in einem Versuch/catch Block:

executor = Executors.newSingleThreadExecutor(); 
final Runnable runnable = new Runnable() { 

@Override 
    public void run() { 
    try { 
    doSomething(); 
    } catch (Exception exception) { 
     throw new RuntimeException(exception); 
    } 
    } 
}; 

try{ 
executor.submit(runnable); 
} catch (Throwable t) { 
    Throwable cause = t.getCause(); 
    //do what you want with the cause 
} 
Verwandte Themen