TL;DR
Компилятор считает, что FileNotFoundException()
может быть не единственным выброшенным Exception
.
Объяснение
JLS§11.2 .3 Проверка исключений
Компилятору Java рекомендуется выдавать предупреждение, если предложение catch может перехватывать (§11.2) проверенный класс исключений E1, а блок try, соответствующий предложению catch, может генерировать проверенный класс исключений E2, подкласс E1 и предшествующее предложение catch класса непосредственно вложенный оператор try может перехватить проверенный класс исключений E3, где E2 ‹: E3 ‹: E1.
Это означает, что если компилятор считает, что единственным исключением, которое может быть вызвано вашим блоком catch, является FileNotFoundException()
, он предупредит вас о втором блоке catch. Что не так здесь.
Однако следующий код
try{
throw new FileNotFoundException();
} catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e){ // The compiler warns that all the Exceptions possibly
// catched by IOException are already catched even though
// an IOException is not necessarily a FNFException
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
Это происходит потому, что компилятор оценивает блок try, чтобы определить, какие исключения могут быть выброшены.
Поскольку компилятор не предупреждает нас о Èxception e
, он считает, что могут быть выброшены другие исключения (например, RunTimeException). Поскольку обработка этих исключений RunTimeException не является задачей компилятора, он позволяет этому проскользнуть.
Остальную часть ответа интересно прочитать, чтобы понять механизм перехвата исключений.
Схема
Как видите, Exception
находится выше в иерархии, поэтому его нужно объявлять последним после IOException
, который находится ниже в иерархии.
Пример
Представьте, что вам бросили IOException
. Поскольку он унаследован от Exception
, мы можем сказать, что IOException IS-A Exception, и поэтому он всегда будет перехватываться в блоке Exception
, а блок IOException
будет недоступен.
Пример из реальной жизни
Допустим, вы в магазине и вам нужно выбрать брюки. Продавец говорит вам, что вы должны попробовать брюки от самых больших до самых маленьких, и если вы найдете те, которые вы можете носить (даже если они не вашего размера), вы должны взять их.
Вы обнаружите, что покупаете штаны слишком велики для своего размера, и у вас не будет возможности найти штаны, которые вам подходят.
Вы идете в другой магазин: там происходит прямо противоположное. Вы можете выбрать брюки от самых маленьких до самых больших, и если вы найдете то, что сможете надеть, вы должны взять его.
Вы обнаружите, что покупаете брюки именно своего размера.
Это небольшая аналогия, немного странная, но она говорит сама за себя.
Начиная с Java 7, у вас есть возможность включить все типы исключений, которые могут быть вызваны вашим блоком try, в один единственный блок catch.
ВНИМАНИЕ: Вы также должны соблюдать иерархию, но на этот раз слева направо.
В вашем случае это будет
try{
//doStuff
}catch(IOException | Exception e){
e.printStackTrace();
}
Следующий пример, допустимый в Java SE 7 и более поздних версиях, устраняет дублированный код:
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
Предложение catch указывает типы исключений, которые может обрабатывать блок, и каждый тип исключения отделяется вертикальной чертой (|).
person
Yassin Hajaj
schedule
10.12.2015
catch (Exception e)
в вашем первом случае и почему компилятор не считает его недостижимым. Но похоже, что большинство людей здесь думают, что вы спрашиваете о своем втором примере. Что это? - person sstan   schedule 10.12.2015