Попробуйте Catch Exception Helper - PullRequest
0 голосов
/ 21 июня 2020

Я уже сделал помощник, который возвращает сообщение об ошибке, используя параметр Exception в другой функции. (Это пример)

void func(int n){ 
    try { 
        // this will throw ArithmeticException if n is 0 
        int x = 10 / n; 
        int y[] = new int[n]; 
        y[x] = 10; 

        // this will throw ArrayIndexOutOfBoundsException 
        // if the value of x surpasses 
        // the highest index of this array 
        System.out.println("No exception arose"); 
    } 
    catch (Exception e) { 
        System.out.println(getErrorType(e)); 
    } 
} 

String getErrorType(Exception e){
    String errorMessage = "";
    if (e instanceof ArithmeticException) 
        errorMessage = "ArithmeticException, Can't divide by 0";
    if (e instanceof ArrayIndexOutOfBoundsException) 
        errorMessage = "ArrayIndexOutOfBoundsException, This index doesn't exist in this array";
    else
        errorMessage = "error";
    return errorMessage;
}

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

  • Хорошо ли это использовать в Java?
  • Есть много неудобств, чтобы использовать его таким образом?
  • Есть другой способ реализовать то, что я пытаюсь сделать?
  • Как это влияет на производительность?

Я уже знаю, что хорошее применение в блоках try catch - это использование спецификаций c Добавление исключений уровни перехвата с указанием c Exception, но я хочу сделать его общим c.

Ответы [ 4 ]

0 голосов
/ 22 июня 2020

TL; DR

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

Концепция

Похоже, вы разделяете (широко распространенное) неправильное представление о том, как действовать в исключительных ситуациях, например: «Исключения - это плохо! поймать их как можно раньше! " Это неверно. Исключения идеально подходят для того, чтобы сообщить вызывающему абоненту о моей неудаче: «Я не смог завершить sh свою работу. Вы решаете, можете ли вы обойтись без него, повторите попытку каким-либо другим способом или просто сообщите об этом своему вызывающему абоненту».

У вашего func() есть работа (каким бы ни был этот «контракт»). Исключение, выбрасываемое из метода, предназначено для сообщения о том, что этот метод (полностью) не выполнил свою работу.

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

* 1018 Исключение доходит до вашего вызывающего абонента, он, таким образом, получает информацию о сбое и может решить, может ли он разумно продолжить работу даже после сбоя func().

В большинстве случаев это решение гласит: «Если что-то в моем алгоритме терпит неудачу, все это терпит неудачу, и я немедленно хочу прервать все его вычисления ". И это то, что вы получаете бесплатно от исключений, если ничего не поймаете.

Ваше предложение catch

Вы пытаетесь представить удобное сообщение с описанием проблемы лучше, чем автоматическая c текстовая форма, которую Java Runtime связывает с исключением.

На первый взгляд это кажется правдоподобным, но ...

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

Ответы на ваши вопросы

  • Ваш общий подход имеет некоторые недостатки, как описано выше. Я сомневаюсь, что вы можете создать хорошее, понятное для пользователя сообщение об ошибке только из объекта исключения, независимо от кода, в котором это произошло. А использование instanceof в Java почти всегда плохая идея.
  • Да, это неудобно. Вы пишете много строк без ценной выгоды.
  • Если вы действительно хотите остаться с текстами, зависящими от типа исключения, используйте несколько предложений catch для разных классов исключений. Не думаю, что это имеет значение для производительности. И ваше программное обеспечение должно работать в очень странной области, если производительность обработки ошибок имеет значение.
0 голосов
/ 21 июня 2020

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

Если вам нужна именно такая деталь, лучше повторно генерировать исключение с помощью специального сообщения. Вот тривиальный пример:

int divide (int a, int b) {
    try {
        return a / b;
    } catch (ArithmeticException e) {
        throw new ArithmeticException("Divide by 0", e);
    }
}

Помните, что вы хотите обрабатывать исключения по-другому, потому что вы не хотите, чтобы ваше приложение завершало работу из-за мелких вещей, которые можно исправить - это плохой дизайн. Если ваше приложение сталкивается с проблемой, которую вы можете исправить, например, с ошибкой ввода от пользователя, вы можете перехватить исключение и остановить cra sh. Использование исключения generi c не позволит вам сделать это, потому что вы не будете знать, какое исключение было сгенерировано. Вы можете выполнить эту обработку в своей функции getErrorType, но тогда вы можете получить что-то вроде:

String getErrorType(Exception e){
    String errorMessage = "";
    if (e instanceof ArithmeticException) 
        errorMessage = "ArithmeticException, Can't divide by 0";
        warnUserToChangeValue();
    if (e instanceof IllegalArgumentException) 
        errorMessage = "Bad Argument";
        warnUserToChangeValue();    
    if (e instanceof ArrayIndexOutOfBoundsException) 
        errorMessage = "ArrayIndexOutOfBoundsException, This index doesn't exist in this array";
    else
        errorMessage = "error";
    return errorMessage;
}

Это действительно трудно читать. Я бы рекомендовал сделать это простым и просто поймать в соответствии с тем, что вам нужно:

catch (ArithmeticException e |  IllegalArgumentException e) 
{
    // The user probably entered a bad value, no reason to terminate, just tell them
    warnUserToChangeValue(); 
}
0 голосов
/ 21 июня 2020

Перехват Exception в целом является плохой практикой, потому что он также будет поглощать несвязанные ошибки, такие как NullPointerException, IllegalStateException, IllegalArgumentException и другие RuntimeExceptions, которые являются ОШИБКАМИ и действительно должны продолжать распространяться.

Итак, использование:

catch (ArithmeticException | SomeOtherException e) {
   ...
}

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

Это ошибка.

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

В таких случаях ловля метательного оружия более эффективна.

0 голосов
/ 21 июня 2020

Как правило, вы хотите указать Exception, которое вы ожидаете, в предложениях try / catch, чтобы, когда другие люди go через ваш код, они знали, какие исключения ожидать, если им когда-либо понадобится обрабатывать их.

На самом деле вы можете объединить свои предложения catch в один, сделав что-то вроде этого:

try { 
    // this will throw ArithmeticException if n is 0 
    int x = 10 / n; 
    int y[] = new int[n]; 
    y[x] = 10; 

    // this will throw ArrayIndexOutOfBoundsException 
    // if the value of x surpasses 
    // the highest index of this array 
    System.out.println("No exception arose"); 
} 
catch (ArithmeticException | ArrayIndexOutOfBoundsException | SomeOtherException e) { 
    e.printStackTrace(); 
} 
...