Обработка причины ExecutionException
Предположим, у меня есть класс, определяющий большой блок работы, который может произвести несколько проверенных исключений.
class WorkerClass{
public Output work(Input input) throws InvalidInputException, MiscalculationException {
...
}
}
Теперь предположим, что у меня есть графический интерфейс, который может вызывать этот класс. Я использую 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.
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
}
Вы можете использовать некрасивый (умный?) Хак, чтобы преобразовать бросаемый объект в непроверенное исключение. Преимущество состоит в том, что вызывающий код будет получать любое исключение, которое было сгенерировано вашим рабочим потоком, независимо от того, отмечен он или нет, но вам не нужно изменять сигнатуру вашего метода.
try {
future.get();
} catch (InterruptedException ex) {
} catch (ExecutionException ex) {
if (ex.getCause() instanceof InvalidInputException) {
//do your stuff
} else {
UncheckedThrower.throwUnchecked(ex.getCause());
}
}
С UncheckedThrower
определяется как:
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;
}
}
Попробуйте / мульти-улов:
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
}
}