java exception handling

260
16 июля 2018, 03:40

В какой ситуации нужно выбрасывать ошибки, а в кокой их нужно обрабатывать? Например в конструкторе класса SoundClipBase мы передаем путь к файлу, и в случае передачи null мы выбрасываем исключение или обрабатываем его? Очень важно что бы было в дальнейшем возможно написать эффективный тест на конструктор.

    public SoundClipBase(String path) throws FileNotFoundException{
         if(path == null || path.isEmpty())
             throw new IllegalArgumentException("sound clip can't be null or empty");
         setPath(path);
         audioClip = new AudioClip(getClass().getResource(path).toString());
     }

Та же ситуация в методе setPath. При некоректном пути нужно ли выкидывать исключение?

public void setPath(String path) throws FileNotFoundException {
    if(path.endsWith(".wav"))
        this.path = path;
    else
        throw new FileNotFoundException("invalid path");
}
Answer 1

Сразу оговорюсь что нет золотого правила о том где и когда обрабатывать Exception, а следовательно всё это довольно субъективно.

Лично я стараюсь обрабатывать ошибку там, где это требуется логикой программы либо в месте ответственности за вызванную ошибку. Постараюсь объяснить свою мысль на абстрактном примере.Представим что есть математическая библиотека у которой есть метод для решения квадратного уравнения.

public Pair solveQuadratic (string input){
    Quadratic quadratic = Quadratic.parse(input);
    Pair result;
    result = tryVieta(quadratic);
    result = tryDiscriminant(quadratic);
    return result;
}

В данном примере у нас возможны 3 ошибки:

  1. ParseException, когда мы преобразуем строку в объект
  2. InvalidParameter, когда мы пытаемся вызвать решение методом Виета для уравнения, которое нельзя решить теоремой Виета
  3. UnsolvedQuadraticException, если уравнение оказалось не решаемое

Первую ошибку надо выбрасывать методу, который его вызвал, т.к. ни метод решающий уравнения, ни математическая либа не хотят знать что делать если строка не верна. Это задача того, кто метод вызвал. В каком то случае главный процесс ещё раз запросит ввод у пользователя, в каком то преобразует строку, либо вообще заинициализирует Pair нулями. В любом случае, это не головняк приведенного в примере метода.

Вторую ошибку следует обрабатывать внутри метода, так как снаружи не должно быть известно и вообще не волнует, как именно решит уравнение метод, важен результат. Если запихнуть в метод корректное уравнение, а метод вернет что то типа "Это уравнение не вида Виета", то это будет нарушением ответственности за ошибку.

Обработка третьей ошибки зависит от вашего представления, что должно вернуться, если уравнение не решаемое: null или Exception. Если считаете что null, то ошибка обрабатывается внутри, а иначе иначе)) Я преподчитаю выбрасывать Exception

По итогу наш метод превратится в следующий

public Pair solveQuadratic (string input) throw ParseException, UnsolvedQuadraticException{
    Quadratic quadratic = Quadratic.parse(input);
    Pair result;
    try{
        result = tryVieta(quadratic);
    }catch(InvalidParameterException e){
        result = tryDiscriminant(quadratic);
    }
    return result;
}

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

Answer 2

Про это можно почитать в 9-й главе "Effective Java" Джошуа Блоха. Если в общих чертах, то можно свести к двум рекомендациям:

  • Если в в методе могут возникнуть исключения, которые метод способен обработать так, чтобы продолжить работу и выполнить свою функцию, то его надо обработать внутри метода. Если возникающее исключение исключает выполнение основной функции метода, то надо выбросить исключение наружу.
  • Метод должен выбрасывать исключения, соответствующие абстракции. Если метод выбрасывает исключение, не имеющее видимой связи с решаемой задачей, это сбивает с толку. Часто это происходит, когда метод передаёт выше исключение, выброшенное абстракцией нижнего уровня. Во избежание этой проблемы верхние уровни приложения должны перехватывать исключения нижних уровней и, в свою очередь, выбрасывать исключения, которые можно объяснить в терминах абстракции верхнего уровня.
READ ALSO
Hashcode java и его формирование

Hashcode java и его формирование

Подскажите пожалуйста, должен ли Hashcode объекта измениться если его поля изменились?

193
Тетрис на Android

Тетрис на Android

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

193
Cмаппить поле из типа определенным пользователем в cassandra с полем в java

Cмаппить поле из типа определенным пользователем в cassandra с полем в java

Как можно смаппить поле из типа определенным пользователем с полем в java со spring data

205
создание background через переопределение paintComponent

создание background через переопределение paintComponent

помогите разобраться, хочу сделать background (добивать изображение на основной фон), собственно добавление идет строками

164