Студопедия  
Главная страница | Контакты | Случайная страница

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

Повторное выбрасывание исключений

Читайте также:
  1. Автоматическое Повторное Включение
  2. Базовая иерархия классов исключений
  3. Глава 10. Расширение и растворение «я»: тёмная ночь и повторное рождение
  4. Глава 10. Расширение и растворение «я»: тёмная ночь и повторное рождение.
  5. Избегайте ненужных обрабатываемых исключений
  6. Назвать модели обработки исключений и написать для каждой из них шаблон кода.
  7. Наследование: повторное использование интерфейса
  8. Не игнорируйте исключений
  9. Обработка исключений
  10. Обработка исключений: работа с ошибками

Иногда вам будет нужно вновь выбросить исключение, которое вы только что поймали, обычно это происходит, когда вы используете Exception, чтобы поймать любое исключение. Так как вы уже имеете ссылку на текущее исключение, вы можете просто вновь бросить эту ссылку:

catch(Exception e) { System.err.println("An exception was thrown"); throw e;}

Повторное выбрасывание исключения является причиной того, что исключение переходит в обработчик следующего, более старшего контекста. Все остальные предложения catch для того же самого блока try игнорируются. Кроме того, все, что касается объекта исключения, сохраняется, так что обработчик старшего контекста, который поймает исключение этого специфического типа, может получить всю информацию из этого объекта.

Если вы просто заново выбросите текущее исключение, то информация, которую вы печатаете об этом исключении, в printStackTrace() будет принадлежать источнику исключения, а не тому месту, откуда вы его вновь выбросили. Если вы хотите установить новый стек информации трассировки, вы можете сделать это, вызвав функцию fillInStackTrace(), которая возвращает объект исключения, для которого текущий стек наполняется информацией для старого объекта исключения. Вот как это выглядит:

//: c10:Rethrowing.java// Демонстрация fillInStackTrace() public class Rethrowing { public static void f() throws Exception { System.out.println("originating the exception in f()"); throw new Exception("thrown from f()"); } public static void g() throws Throwable { try { f(); } catch(Exception e) { System.err.println("Inside g(), e.printStackTrace()"); e.printStackTrace(System.err); throw e; // 17 // throw e.fillInStackTrace(); // 18 } } public static void main(String[] args) throws Throwable { try { g(); } catch(Exception e) { System.err.println("Caught in main, e.printStackTrace()"); e.printStackTrace(System.err); } }} ///:~

Важные строки помечены комментарием с числами. При раскомментированной строке 17 (как показано), на выходе получаем:

originating the exception in f()Inside g(), e.printStackTrace()java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:8) at Rethrowing.g(Rethrowing.java:12) at Rethrowing.main(Rethrowing.java:24)Caught in main, e.printStackTrace()java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:8) at Rethrowing.g(Rethrowing.java:12) at Rethrowing.main(Rethrowing.java:24)

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

Если закомментировать строку 17, а строку 18 раскомментировать, будет использоваться функция fillInStackTrace(), и получим результат:

originating the exception in f()Inside g(), e.printStackTrace()java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:8) at Rethrowing.g(Rethrowing.java:12) at Rethrowing.main(Rethrowing.java:24)Caught in main, e.printStackTrace()java.lang.Exception: thrown from f() at Rethrowing.g(Rethrowing.java:18) at Rethrowing.main(Rethrowing.java:24)

Поскольку fillInStackTrace() в строке 18 становится новой исходной точкой исключения.

Класс Throwable должен появиться в спецификации исключения для g() и main(), потому что fillInStackTrace() производит ссылку на объект Throwable. Так как Throwable - это базовый класс для Exception, можно получить объект, который является Throwable, но не Exception, так что обработчик для Exception в main() может промахнуться. Чтобы убедится, что все в порядке, компилятор навязывает спецификацию исключения для Throwable. Например, исключение в следующем примере не перехватывается в main():

//: c10:ThrowOut.javapublic class ThrowOut { public static void main(String[] args) throws Throwable { try { throw new Throwable(); } catch(Exception e) { System.err.println("Caught in main()"); } }} ///:~

Также возможно вновь выбросить исключение, отличающееся от того, которое вы поймали. Если вы делаете это, вы получаете сходный эффект, как если бы вы использовали fillInStackTrace() — информация об оригинальном состоянии исключения теряется, а то, с чем вы остаетесь - это информация, относящаяся к новому throw:

//: c10:RethrowNew.java// Повторное выбрасывание объекта,// отличающегося от пойманного. class OneException extends Exception { public OneException(String s) { super(s); }} class TwoException extends Exception { public TwoException(String s) { super(s); }} public class RethrowNew { public static void f() throws OneException { System.out.println("originating the exception in f()"); throw new OneException("thrown from f()"); } public static void main(String[] args) throws TwoException { try { f(); } catch(OneException e) { System.err.println("Caught in main, e.printStackTrace()"); e.printStackTrace(System.err); throw new TwoException("from main()"); } }} ///:~

Вот что напечатается:

originating the exception in f()Caught in main, e.printStackTrace()OneException: thrown from f() at RethrowNew.f(RethrowNew.java:17) at RethrowNew.main(RethrowNew.java:22)Exception in thread "main" TwoException: from main() at RethrowNew.main(RethrowNew.java:27)

Конечное исключение знает только то, что оно произошло в main(), а не в f().

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




Дата добавления: 2015-09-11; просмотров: 26 | Поможем написать вашу работу | Нарушение авторских прав

Хеширование и хеш-коды | Фактор производительности HashMap | Хранение ссылок | Выбор реализации | Неподдерживаемые операции | Vector и Enumeration | Hashtable | Упражнения | Обработка ошибок с помощью исключений | Создание ваших собственных исключений |


lektsii.net - Лекции.Нет - 2014-2024 год. (0.006 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав