Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Исключения – советы по использованию, Старые и новые способы обработки 
:(
    Опции темы
AntonSaburov
Дата 24.1.2008, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 51
Всего: 118



Исключения – советы по использованию

(Оригинал на сайте - JAVA-технологии)

Обработка исключений – это встроенная возможность языка JAVA. Концепция обработки исключений позволяет сделать код более надежным и позволяет лучше читать и сопровождать его. Давайте посмотрим на конструкцию для обработки исключения:

Код

try {

   // code which could potentially
   // throw an exception

} catch (TheException1 e) {

   // code to handle exceptional condition

} catch (TheException2 e) {

   // code to handle next exceptional condition

} finally {

   // code to run whether an exceptional 
   // condition happened or not
    
}


В основном, код, который может вызвать исключение помещается в такую конструкцию. Блок catch описываемый для определенного исключения будет вызываться – т.е. если случится исключение TheException1, тогда будет вызван блок внутри его catch. Однако блок finally будет вызываться всегда, даже если какой-либо блок catch содержит return.
Таким образом думаю понятно, что блок try должен быть всегда. И всегда должен быть хотя бы один из блоков catch или finally.
Исходя из того, что блоков catch может быть много, система в случае исключения будет искать первый подходящий тип исключения. Причем с учетом наследования. Т.е. если вы ловите исключение IOException, то исключение FileNotFoundException, которрое является подклассом IOException будет обрабатываться в блоке try, который содержит IOException. Думаю, что это несложно.

Первый совет по обработке исключений: старайтесь обрабатывать специфические исключения. Т.е. если вы создали метод, который будет генерировать исключение FileNotFoundException – не декларируйте, что метод взывает исключение IOException. Нехорошо заставлять пользователя вашим классом обрабатывать исключение более высокого уровня, чем надо в действительности.

Второй совет: не делайте пустых catch блоков. Иными словами не делйте такой код.

Код

try {
     ...
} catch (AnException e) {
}


Если даже логика вашего кода подразумевает полное отсуствие каких-либо действий при исключении – не поленитесь и напишите комментарий. Иначе пользватели вашего кода будут в затруднении.

Еще один добрый совет: Если метод класса вызывает исключение – пишите на него документацию. Используйте тэг @throws.

Код

/**
 * Loads the class
 *
 * @param  name
 *         Class name
 *
 * @return  Resulting <tt>Class</tt> object
 *
 * @throws  ClassNotFoundException
 *          If class not found
 */
public Class loadClass(String name) throws ClassNotFoundException 
{
        ...
}


Наверняка вы знаете о RuntimeException и его подклассах. Эти исключения не требуют, чтобы их обрабатывали. И вообщем не всегда их обработка будет выглядет логичной и нужной.
Но в некоторых случаях это будет логично и понятно. Например если вы ожидаете от пользователя ввода целого числа, которе вводится как строка. Для преобразования скорее всего будет использован методв parseInt, который вызывает runtime исключение NumberFormatException. Обычно runtime исключения обрабатываются тогда, когда необходимо восстановление при таких исключениях. Как в выше приведенном примере с parseInt.


Новые возможности Java 1.5 – UncaughtExceptionHandler

Мы уже говорили о том, что есть non-runtime исключения, которые вы обязаны помещать в блок try/catch и runtime, которые не требуют специальной обработки. Но бывают случаи, когда требуется обрабатывать и их – например вы хотите выводить все сообщения в определенном формате в какое-то окно сообщений. Расставлять по всему коду блоки try/catch конечно не очень удобное занятие.
Существуют три способа сделать обработку runtime исключений.
1.    Вызвать метод setUncaughtExceptionHandler() у класса Thread.
2.    Определить свой класс ThreadGroup и переопределить метод uncaughtException().
3.    Вызвать статический метод класса Thread - setDefaultUncaughtExceptionHandler().

Методы setUncaughtExceptionHandler() и setDefaultUncaughtExceptionHandler() принимают в качестве аргумента класс, который реализует интерфейс UncaughtExceptionHandler.
Этот интерфейс имеет всего один метод 

Код

void uncaughtException(Thread t, Throwable e)


Рассмотрим в качесвте примера два класса.

Первый класс представляет из себя окно, которое будет «всплывать» при возникновении исключнения. Окно реализует интерфейс UncaughtExceptionHandler.
Надо обратить внимание на два момента:
1.    Это метод uncaughtException. Он реализует интерфейс 
2.    Метод addStackInfo. Вообщем-то в нем и происхожит основная работа.

Чтобы вы не пугались - EventQueue.invokeLater представляет из себя метод, который вызывается «в очереди» и что важно отметить делается асинхронно (в отдельном треде).

Все остальные вызовы достаточно очевидны – сделать окно видимым, вывести его на передний план, создать два потока для печати строк и вывести строки. Вообщем-то и все.

Код

import java.awt.*;
import java.io.*;
import javax.swing.*;

public class StackWindow extends JFrame implements Thread.UncaughtExceptionHandler 
{
  private JTextArea textArea;

  public StackWindow(String title, final int width, final int height) 
  {
    super(title);
    setSize(width, height);
    textArea = new JTextArea();
    JScrollPane pane = new JScrollPane(textArea);
    textArea.setEditable(false);
    getContentPane().add(pane);
  }

  public void uncaughtException(Thread t, Throwable e) 
  {
    addStackInfo(e);
  }

  public void addStackInfo(final Throwable t) 
  {
    EventQueue.invokeLater(new Runnable() 
    {
      public void run() {
        // Bring window to foreground
        setVisible(true);
        toFront();
        // Convert stack dump to string
        StringWriter sw = new StringWriter();
        PrintWriter out = new PrintWriter(sw);
        t.printStackTrace(out);
        // Add string to end of text area
        textArea.append(sw.toString());
      }
    });
  }
}


Второй класс сделан для тогоЮ чтобы продемонстрировать работу нашего окошка. Откомпилируйте и запускайте.

Код

import java.io.*;

public class DumpTest 
{
  public static void main(final String args[]) throws Exception 
  {
    Thread.UncaughtExceptionHandler handler =
      new StackWindow("Show Exception Stack", 400, 200);
    Thread.setDefaultUncaughtExceptionHandler(handler);
    new Thread() {
      public void run() {
        System.out.println(1 / 0);
      }
    }.start();
    BufferedReader br =
      new BufferedReader(new InputStreamReader(System.in));
    System.out.print("Press Enter for next exception");
    br.readLine();
    new Thread() {
      public void run() {
        System.out.println(args[0]);
      }
    }.start();
    System.out.print("Press Enter to end");
    br.readLine();
    System.exit(0);
  } 
}


При запуске вы увидите окошко с ошибкой. Его можно закрыть и в консольном окне (где запущено приложение) нажмите Enter (как предлагается). И снова увидите окно с ошибкой. Причем важно отметить, что обе ошибки – runtime, но программа нормально продолжает свою работу.

PM MAIL WWW ICQ   Вверх
Samotnik
Дата 24.1.2008, 14:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Super star !
****


Профиль
Группа: Awaiting Authorisation
Сообщений: 7192
Регистрация: 4.11.2006
Где: Минск City

Репутация: 8
Всего: 191



Очень хорошо, спасибо вам !!    smile 
PM MAIL   Вверх
Maksym
Дата 24.1.2008, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.
***


Профиль
Группа: Участник Клуба
Сообщений: 1456
Регистрация: 19.8.2005
Где: Odessa, Black Sea

Репутация: 14
Всего: 62



AntonSaburov
А как правильнее прицепить такого слушателя необработанных исключений к дефолтному (текущему) потоку (который в при запуске приложения jvm создает)?

PM MAIL   Вверх
AntonSaburov
Дата 24.1.2008, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 51
Всего: 118



По идее вызвать Thread.currentThread() - получим ссылку на текущий тред. И у него вызывать setUncaughtExceptionHandler().

PM MAIL WWW ICQ   Вверх
Maksym
Дата 24.1.2008, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.
***


Профиль
Группа: Участник Клуба
Сообщений: 1456
Регистрация: 19.8.2005
Где: Odessa, Black Sea

Репутация: 14
Всего: 62



AntonSaburov
Ага. Сенкс.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0862 ]   [ Использовано запросов: 23 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.