2013-02-06 49 views
4

假設我有一個類定義了要完成的大塊工作,可以產生多個檢查的異常。處理ExecutionException的原因

class WorkerClass{ 
    public Output work(Input input) throws InvalidInputException, MiscalculationException { 
     ... 
    } 
} 

現在假設我有一種可以調用這個類的GUI。我使用SwingWorker來委派任務。

Final Input input = getInput(); 
SwingWorker<Output, Void> worker = new SwingWorker<Output, Void>() { 
     @Override 
     protected Output doInBackground() throws Exception { 
      return new WorkerClass().work(input); 
     } 
}; 

如何處理SwingWorker引發的可能異常?我想區分工人類的異常(InvalidInputException和MiscalculationException),但是ExecutionException包裝會使事情複雜化。我只想處理這些異常 - 不應該發現OutOfMemoryError。

try{ 
    worker.execute(); 
    worker.get(); 
} catch(InterruptedException e){ 
    //Not relevant 
} catch(ExecutionException e){ 
    try{ 
     throw e.getCause(); //is a Throwable! 
    } catch(InvalidInputException e){ 
     //error handling 1 
    } catch(MiscalculationException e){ 
     //error handling 2 
    } 
} 
//Problem: Since a Throwable is thrown, the compiler demands a corresponding catch clause. 
+0

可能重複(http://stackoverflow.com/questions/10437890/what-is-最好的方式來處理執行異常) – Sjoerd

回答

3
catch (ExecutionException e) { 
    Throwable ee = e.getCause(); 

    if (ee instanceof InvalidInputException) 
    { 
     //error handling 1 
    } else if (ee instanceof MiscalculationException e) 
    { 
     //error handling 2 
    } 
    else throw e; // Not ee here 
} 
+0

在我的意見中是最乾淨的答案。 – DieterDP

+2

在某些情況下,我們懷疑這個方法是否會在拋出一個意外的異常(或錯誤)時工作,而不是'throw e'你很多人想要拋出新的RuntimeException(ee)' –

0

嘗試/多陷阱:

try { 
    worker.execute(); 
    worker.get(); 
} catch (InterruptedException e) { 
    //Not relevant 
} catch (InvalidInputException e) { 
    //stuff 
} catch (MiscalculationException e) { 
    //stuff 
} 

或者與ExecutionException包裝:

catch (ExecutionException e) { 
    e = e.getCause(); 
    if (e.getClass() == InvalidInputException.class) { 
     //stuff 
    } else if (e.getClass() == MiscalculationException.class) { 
     //stuff 
    } 
} 

或者,如果你希望得到的例外子像他們的父母:

catch (ExecutionException e) { 
    e = e.getCause(); 
    if (e instanceof InvalidInputException) { 
     //stuff 
    } else if (e instanceof MiscalculationException) { 
     //stuff 
    } 
} 
+0

心理解釋downvote? – Doorknob

+0

這不會工作,因爲InvalidInputException和MiscalculationException永遠不會引發這一點。只有包含這些的ExectuionException可能發生。 – DieterDP

+0

@DieterDP好吧,更新後 – Doorknob

1

您可以使用ugly (smart?) hack將throwable轉換爲未經檢查的異常。優點是調用代碼將接收工作線程拋出的任何異常,無論是選中還是未選中,但不必更改方法的簽名。

try { 
    future.get(); 
} catch (InterruptedException ex) { 
} catch (ExecutionException ex) { 
    if (ex.getCause() instanceof InvalidInputException) { 
     //do your stuff 
    } else { 
     UncheckedThrower.throwUnchecked(ex.getCause()); 
    } 
} 

隨着UncheckedThrower定義爲:?什麼是處理爲ExecutionException的最佳方式]的

class UncheckedThrower { 

    public static <R> R throwUnchecked(Throwable t) { 
     return UncheckedThrower.<RuntimeException, R>trhow0(t); 
    } 

    @SuppressWarnings("unchecked") 
    private static <E extends Throwable, R> R trhow0(Throwable t) throws E { 
     throw (E) t; 
    } 
} 
+0

。我會期待一個額外的ClassCastException,但它不會發生。這種方法的作用像一個魅力,但我不知道它爲什麼這樣做:D 你有任何參考解釋它爲什麼? +1因爲我學到了新東西。 – DieterDP

+0

@DieterDP泛型魔術 - 不確定它是如何工作的詳細說實話。可能是語言的一些模糊規則! – assylias

+0

您提供的鏈接提供了一個提示...此代碼的Java字節碼版本不會對類型進行實際檢查。我懷疑它與Exception層次結構有些「奇怪」有關,其中RuntimeException是Exception的子類,但不需要聲明,在正常Exception的情況下。 – DieterDP

相關問題