2013-08-21 2 views
3
import java.io.*; 
class ex3 
{ 

    public static void main(String args[]) 
    { 
     myfun(); 
    } 

    static void myfun() 
    { 
     try 
     { 
      FileInputStream f = new FileInputStream("file.ytxt"); 
      System.out.println("my fun"); 
     } 

     catch(Exception e) //Line 1 
     { 
      System.out.println(e.getMessage()); 
     } 

     catch(FileNotFoundException e) //Line 2 
     { 
      System.out.println("File Not Found Caught"); 
     } 
    } 
} 

Я создал два кода обработчика исключений (один общий и другой, определенный в строках 1 и 2).Как компилятор знает об исключениях, которые необходимо выполнить перед выполнением?

Мой компилятор жалуется

ex3.java:24: error: exception FileNotFoundException has already been caught 
       catch(FileNotFoundException e) 
       ^
1 error 

Мой вопрос, как же компилятор знает, что «FileNotFoundException» будет сгенерировано блоком попробовать?

+1

Потому что декларация метода (конструктора) сообщает об этом. –

+0

Прочтите [этот пост] (http://stackoverflow.com/questions/15167899/why-does-order-matter-when-catching-exceptions/15174337#15174337) –

ответ

10

catch(FileNotFoundException e) эта линия недостижима. Так как:

FileNotFoundException extends Exception

См Exception и FileNotFoundException:

enter image description here

Вы, вероятно, хотите, чтобы переключить их порядок.

4

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

Когда вы поймаете Exception, он также поймает любой подкласс Исключения, например FileNotFoundException.

Своп порядок зажимных блоков к этому:

catch(FileNotFoundException e) //Line 2 
    { 
     System.out.println("File Not Found Caught"); 
    } 
    catch(Exception e) //Line 1 
    { 
     System.out.println(e.getMessage()); 
    } 
6

Ваша проблема лежит где-то в другом месте. FileNotFoundException всегда будет попадать в Exception, потому что это базовый класс для всех исключений. Так компилятор в основном жалуется на кусок мертвого кода, который

catch(FileNotFoundException e) { 
    System.out.println("File Not Found Caught"); 
} 

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

+0

+1 для * более мелкозернистой обработки EXT *. – Maroun

1

Изменить это -

catch(Exception e) //Line 1 
    { 
     System.out.println(e.getMessage()); 
    } 

    catch(FileNotFoundException e) //Line 2 
    { 
     System.out.println("File Not Found Caught"); 
    } 

к этому -

catch(FileNotFoundException e) //Line 1 
    { 
     System.out.println(e.getMessage()); 
    } 
    catch(Exception e) //Line 2 
    { 
     System.out.println("File Not Found Caught"); 
    } 

Exception - это супер тип всех классов исключений в Java. Таким образом, любой объект исключения может быть назначен для ссылки типа Exception. Когда в вашей программе возникает исключение, блоки catch проверяются последовательно сверху вниз, чтобы найти совпадение между типом произошедшего исключения и типом исключения, которое обрабатывает блок catch. В результате любой тип исключений, сгенерированных в вашем блоке try, всегда будет считать первый блок catch как совпадение, а второй блок catch никогда не может быть достигнут из вашего кода. Именно поэтому компилятор жалуется.

0

Дело не в этом: catch(Exception e) поймает любые Exception, то есть FileNotFoundException. Ловля FileNotFoundException во второй раз бесполезна.

Поймать первый FileNotFoundException, затем Exception.

0

Блок catch будет перехватывать исключения указанного класса и всех его подклассов. Как упоминалось другой FileNotFoundException подкласс Exception и так будет поймано пунктом в

catch (Exception e) 

.

2

Чтобы ответить

Мой вопрос, как же компилятор знает, что «FileNotFoundException» будет сгенерировано блоком попробовать?

Вы должны смотреть на конструктор для FileInputStream

public FileInputStream(String name) throws FileNotFoundException { 
    this(name != null ? new File(name) : null); 
} 

Обратите внимание, что throws FileNotFoundException. Это объявление говорит компилятору, что возможно FileNotFoundException, поэтому обязательно обработайте его с помощью блока try-catch или пусть он пузырится на стеке методов с другим предложением throws.

Что касается ошибки, которую вы получаете, посмотрите на все другие ответы.

+1

+1 для ответа на явный вопрос. –

2

Здесь есть пара вещей.

Во-первых, компилятор знает, что может быть выбрано FileNotFoundException из-за сигнатуры метода FileInputStream. От the docs:

public FileInputStream(String name) throws FileNotFoundException 

Таким образом, подпись говорит компилятору, что он может бросить FileNotFoundException.

Однако в этом случае эта информация фактически несущественна из-за заказа ваших блоков catch. У вас есть:

catch(Exception e) { /* ... */ } 
catch(FileNotFoundException e) { /* ... */ } 

Путь catch блоки работают, если исключение в try блоке, выполнение проходит через каждый cacth блок и смотрит, чтобы увидеть, если тип исключения в catch блоке является полиморфным ровня заброшенное исключение. Так как FileNotFoundException происходит от Exception (см. here), он соответствует первому блоку и всегда будет. Таким образом, второй блок недоступен.

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

При определении блоков catch всегда ставьте их по порядку наименее, чтобы избежать этой проблемы.

1
catch(Exception e) 
    { 
     System.out.println(e.getMessage()); 
    } 

    catch(FileNotFoundException e) 
    { 
     System.out.println("File Not Found Caught"); 
    } 

Исключение - это суперкласс всех исключений.

Итак, если мы используем catch (Exception e) {}, тогда он может поймать все типы исключений.

Таким образом, улов (FileNotFoundExecption f) {} будет недоступен, поэтому компилятор даст сообщение об ошибке, которое уже было обнаружено.

Это правильный способ написать это:

catch(FileNotFoundException e) 
    { 
     System.out.println("File Not Found Caught"); 
    } 
    catch(Exception e) 
    { 
     System.out.println(e.getMessage()); 
    } 
0

Java Virtual Machine Specification: Exceptions

Каждый метод в виртуальной машине Java может быть связан с нулем или более обработчиков исключений. Обработчик исключений определяет диапазон смещений в код виртуальной машины Java, реализующий метод для , который активен обработчик исключений, описывает тип исключения , который обработчик исключений способен обрабатывать, и указывает местоположение кода то есть обработать это исключение. Исключение соответствует обработчику исключений, если смещение инструкции, вызванное исключением , относится к диапазону смещений исключения обработчик, а тип исключения - тот же класс, что или подкласс класса , класс исключения, исключение обработчик. Когда выбрано исключение , виртуальная машина Java ищет соответствующий обработчик исключений в текущем методе. Если найдено соответствующее совпадение , система переходит к коду обработки исключений , указанному согласованным обработчиком.

Порядок поиска обработчиков исключений для метода . Внутри файла класса обработчики исключений для каждый метод хранится в таблице (§4.7.3). Во время выполнения, когда выбрано исключение , виртуальная машина Java ищет исключение обработчиков текущего метода в том порядке, в котором они отображаются в соответствующей таблице обработчика исключений в файле класса, начиная с . Начало этой таблицы ,

Если JDK скомпилирует такой код, блок FileNotFoundException будет недоступен. Из-за объекта исключения проверяется instanceof, он всегда попадает в первый блок исключений. В вашем случае правильная таблица будет:

Exception table: 
    from to target type 
    0 18 21 Class java/io/FileNotFoundException 
    0 18 33 Class java/lang/Exception 

где from и to это номера команд. Стол просматривается сверху вниз.

Смежные вопросы