Создание связанного списка исключений в Java - PullRequest
17 голосов
/ 04 февраля 2010

У меня есть функция, которая зацикливается при выполнении чего-то, что может вызвать исключение. Выглядит примерно так:

public void myFunction() throws MyException {
    while(stuff) {
        try {
            DoSomething() // throws an exception
        }
        catch (Exception ex) {
            throw new MyException(some, stuff, of, mine, ex);
        }
    }
}

Ошибка, вызывающая исключение, исправима. Это может быть что-то вроде ошибки SQL в одном операторе обновления, когда цикл while выполняет серию операторов обновления. Или ошибка синтаксического анализа в одном фрагменте данных, когда цикл обрабатывает несколько фрагментов данных. Мне нужно передать исключение дальше по цепочке, чтобы часть программы с графическим интерфейсом могла обработать его, обработать и передать ошибку пользователю. Но я не хочу уничтожать цикл в этой конкретной функции. Другие вещи, которые он делает, могут быть недействительными. Ошибка, которая вызвала исключение, не может быть фатальной для функции.

Итак, мой вопрос таков: Является ли приемлемой практика для создания связанных списков пользовательских исключений (где каждое исключение является узлом, а выбрасываемое исключение является главой списка), а затем выбрасывает голову список (если есть) после завершения цикла?

Кто-нибудь когда-нибудь видел, чтобы это было сделано? Кто-нибудь может подумать о возможных проблемах с этим? Может кто-нибудь придумать другие, более эффективные способы решения основной проблемы: необходимость пропустить несколько несвязанных исключений без выхода из функции до тех пор, пока это не будет сделано?

Вот пример того, как связывание и бросок могут быть реализованы очень просто:

public void myFunction() throws MyException {
    MyException head = null;
    while(stuff) {
        try {
            DoSomething() // throws an exception
        }
        catch (Exception ex) {
            MyException tmp = new MyException(some, stuff, of, mine, ex);
            tmp.next(head);
            head = tmp;
        }
    }
    if(head != null)
       throw head;
}

Ответы [ 7 ]

16 голосов
/ 04 февраля 2010

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

Я бы вместо этого построил список ошибочных параметров / аргументов при возникновении исключений, и после завершения цикла, сгенерировал бы пользовательское исключение, заполненное этим списком (если список содержит более 0 элементов). Это казалось бы более управляемым способом обработки этого сценария.

public void myFunction() throws CustomException {
    List<MyError> errors = new ArrayList<MyError>();
    while(stuff) {
        try {
            DoSomething() // throws an exception
        }
        catch (Exception ex) {
            errors.add(new MyError(some, stuff, of, mine, ex));
        }
    }
    if (errors.size() > 0) {
       throw new CustomException(errors);
    }
}
3 голосов
/ 04 февраля 2010

Если эти исключения действительно не связаны друг с другом, так что вы не можете воспользоваться get/setCause(), то я бы лучше собрал эту информацию в один MyException.

* 1005 Е.Г. *

public void myFunction() throws MyException {
    MyException myException = null;
    while(stuff) {
        try {
            DoSomething() // throws an exception
        }
        catch (Exception ex) {
            if (myException == null) {
                myException = new MyException();
            }
            myException.addException(some, stuff, of, mine, ex);
        }
    }
    if (myException != null) {
        throw myException;
    }
}

Обновление: Брайан обрабатывает именно этот подход более аккуратно. Я бы выбрал это вместо этого:)

3 голосов
/ 04 февраля 2010

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

Если это так, вы можете просто собрать сообщения об ошибках и добавить их в пользовательский класс Exception и выбросить их.

2 голосов
/ 05 февраля 2010

На самом деле, выкидывание любых исключений из такой функции, вероятно, не правильный способ справиться с этим, если ожидается, что будут ошибки.Я бы предложил либо вернуть список (массив) всех возникших исключений / ошибок, либо лучше предоставить объект-обработчик ошибок для функции, которая может работать с исключениями.т.е.:

public interface ErrorHandler
{
    public void handleError( Throwable ex /*, add some context info */ );
}

public void myFunction( ErrorHandler eh )
{   
    while(stuff) {   
        try {   
            DoSomething() // throws an exception   
        }   
        catch (Exception ex) {
            if( eh != null )
                eh.handleError( ex );
        }   
    }   
}   

Это также позволяет обработчику ошибок либо собирать ошибки, чтобы представить их пользователю, либо решить, что вся пакетная операция стала недействительной из-за какой-либо ошибки, и выдать исключение своейпрервать обработку на ранней стадии.

1 голос
/ 05 февраля 2010

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

В Java уже есть интерфейс для этого: java.beans.ExceptionListener

1 голос
/ 04 февраля 2010

Если исключение, генерируемое DoSomething();, может привести к тому же методу, чтобы вызвать другое исключение; это может быть проблемой. Другими словами, если DoSomething(); выдает исключение , потому что вы не обработали предыдущее, возможно, возникла необоснованная ошибка.

0 голосов
/ 04 февраля 2010

IMO, исключение должно быть последним ресурсом, который у вас есть для обработки ошибки. Этого следует избегать, если это возможно. Таким образом, вы можете захотеть передать описание ошибки (создать коды ошибок, передать сообщение или что-то значимое) в графический интерфейс, а не само исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...