2015-08-07 2 views
6

Я хочу обрабатывать исключения из двух разных типов по-разному, а затем делать одни и те же действия для обоих типов исключений. Как это сделать на Java?Конкретные и те же действия при ловле нескольких исключений

В следующем коде показано, что я хочу сделать, но это неверно, поскольку одно исключение не может быть выловлено дважды.

Каков правильный синтаксис для этого?

try { 
    // do something... 
} 
catch (ExceptionA e) { 
    // actions for ExceptionA 
} 
catch (ExceptionB e) { 
    // actions for ExceptionB 
} 
catch (ExceptionA | ExceptionB e) { 
    // actions for ExceptionA & ExceptionB 
} 
+0

Создайте свой собственный пользовательский класс исключений. – ravi

+1

Вы можете поместить код в функции и вызвать функции в блоке catch. – Jens

+0

@Jens Это не решение, это просто разгрузка проблемы в другом месте ... – insidesin

ответ

4

Используйте конструкцию catch (ExceptionA | ExceptionB e). В блоке catch сначала выполните проверку instanceof для e и обрабатывайте типы исключений отдельно. После этого выполните общую обработку для обоих типов. Таким образом, вы можете сделать все, что в одном блоке catch:

try { 
    // do something... 
} catch (ExceptionA | ExceptionB e) { 
    if (e instanceof ExceptionA) { 
     // handling for ExceptionA 
    } else { 
     // handling for ExceptionB 
    } 
    // common handling for both exception types 
} 
+0

Или вы можете вложить две блокировки catch, которые обрабатывают два отдельно друг друга, которые обрабатывают общую часть. порядок будет зависеть, если вещь, которую вы хотите сделать в том или ином, зависит друг от друга :). – Rob

+0

@Mick Mnemonic Я использовал ваше решение, так как оно является наиболее легко читаемым и понятным. –

1

Если вы ищете (ExceptionA | ExceptionB) вы сможете поймать либо и обращаться одинаково, требуется только один сбой. Это по существу только новый (1.7) стенограмма для нескольких Exception условий.

Нет такой вещи, как catch(ExceptionA && ExceptionB).

Например:

readFile { 
    try { 
     open the file; 
     determine its size; 
     determine its content; 
    } catch (fileOpenFailed) { 
     doSomething; 
    } catch (sizeDeterminationFailed) { 
     doSomething; 
    } catch (contentDeterminationFailed) { 
     doSomething; 
    } 
} 

Если вы хотите, чтобы поймать contentDeterminationFailed и sizeDeterminationFailed в качестве единственного exception тогда вы хотели бы создать свой собственный тип exception, который может быть обработан однозначно.

1

Используйте метод для общего кода.

try { 
    // do something... 
} 
catch (ExceptionA e) { 
    // actions for ExceptionA 
    doCommon(parameters); 
} 
catch (ExceptionB e) { 
    // actions for ExceptionA 
    doCommon(parameters); 
} 

..... 

void doCommon(parameters) { 
    // actions for ExceptionA & ExceptionB 
} 

Это будет работать для большинства вещей.
Хотя есть некоторые исключения, такие как return. Для этого вы можете иметь doCommon возвращение кастрированный баран абонент должен вернуть или нет, и использовать его как:

catch (ExceptionA e) { 
    // actions for ExceptionA 
    if (doCommon(parameters)) 
     return; 
} 
catch (ExceptionB e) { 
    // actions for ExceptionA 
    if (doCommon(parameters)) 
     return; 
} 

Решение «родной Java» не существует. JLS указывает (внимание мое):

14.20.1. Выполнение try-catch

Оператор try без блока finally выполняется, сначала выполнив блок try. Тогда есть выбор:

Если выполнение блока try завершается нормально, то никаких действий не предпринимается, и инструкция try завершается нормально.

Если выполнение блока Ьги завершается преждевременно из-за броском значение V, то есть выбор:

Если типа вводного времени V можно присвоить значение (§5.2) а catchable класс исключений любого предложения catch в заявлении try, , затем первое (самое левое) такое предложение catch выбрано.Значение V присваивается параметр выбранного пункта улова, а блока этого пункта поймать выполняется, а затем есть выбор:

Если блок завершается нормально, то оператор попытки завершается нормально ,

Если по какой-либо причине этот блок неожиданно завершает работу, то по этой же причине завершает работу оператор .

Если тип вводного времени V не уступка совместит с catchable класса исключения из любого пункта уловов заявления попробовать, то оператор попытки завершается преждевременно из-за броском значения V.

Таким образом, выполняется только первый блокирующий блок. Невозможно выполнить два блока catch для одного и того же оператора try.

+0

Извлечение метода - это, конечно же, решение. Но мне интересно, есть ли для него встроенная конструкция try/catch. –

+1

Нет, такой конструкции нет. Я обновил свой ответ с соответствующей частью JLS. –

0

Вы можете повторно выдать исключение и обработать его снова:

try { 
    try { 
     // do something 
    } catch(ExceptionA e) { 
     // actions for ExceptionA 
     throw e; 
    } catch(ExceptionB e) { 
     // actions for ExceptionB 
     throw e; 
    } 
} catch(ExceptionA | ExceptionB e) { 
    // Actions for exceptions A or B 
} 

Может быть, ради ясности, вы можете реорганизовывать в методы. Я предполагаю, что исключения проверяются исключениями.

private void doSomethingHelper() throws ExceptionA, ExceptionB { 
    try { 
     // do something 
    } catch(ExceptionA e) { 
     // actions for ExceptionA 
     throw e; 
    } catch(ExceptionB e) { 
     // actions for ExceptionB 
     throw e; 
    } 
} 

public void doSomething() { 
    try { 
     doSomethingHelper(); 
    } catch(ExceptionA | ExceptionB e) { 
     // Actions for exceptions A or B 
    } 
} 
+0

Это не только осложняет ситуацию ... Последний улов решает проблему самостоятельно. – insidesin

+0

@insidesin Я не согласен, это вложенный блок try. Собственный улов может обрабатывать исключение A или B индивидуально, в то время как внешний может выполнять общую обработку либо после внутреннего, либо из другого. – dave

+0

Значит, вы справляетесь с этим дважды по какой причине? Если вам действительно нужно, выполните 'instanceof' .. – insidesin

1

ли решение этого типа работают для вас:

try { 
// do something... 
} catch (ExceptionA | ExceptionB e) { 
    // common code to be called for both... 
    // .... 
    handleException(e) 
} 

//.... 
void handleException(ExceptionA e) { 
    // code for A 
} 
//.... 
void handleException(ExceptionB e) { 
    // code for B 
} 

Таким образом, первый вы общие действия по двум вопросам, после чего у вас есть общий код для каждого из исключений в соответствующий метод. Таким образом, вам не нужно использовать instanceof или ifs.

Другой способ сделать это только с помощью Java конструкции это положить в конце концов, а также:

boolean fail = false; 

try { 
    // your code 
} catch (ExceptionA a) { 
    // exceptionA specific handling 
    fail = true; 
} catch (ExceptionB b) { 
    // exceptionB specific handling 
    fail = true; 
} finally { 
    if (fail) { 
     // common handling 
    } 
} 
+0

Хорошие решения! –

+0

Вы сами пробовали решение? Это не работает для меня, потому что компилятор не может решить метод 'handleException (ExceptionA | ExceptionB)'. Вам придется изменить подпись на 'handleException (Exception e)', которая побеждает цель ... – r0estir0bbe