Выдает предложение в обработке исключений

Я прочитал сотни сообщений о SO об этом, но я до сих пор неясен в этом вопросе.

  • Когда я пишу функцию, подобную этой

     public List<String> getTrackIds(int limit) throws NotConnectedException, UnauthorizedException {
             ...
        } 
    

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

  • . Когда я пытаюсь вызвать эту функцию, тогда ее необходимо написать          try/catch block или записать предложение throws в вызове          функция. Опять же, как я поймаю эти исключения, если я не напишу          блок try/catch?

Ответ 1

С Исключениями вы можете:

  • Используйте блок try catch для их обработки. (Это моя проблема)
  • Объявите их с помощью throws в спецификации метода. (Это не моя проблема, вы имеете дело с ней).

Для последней возможности, вызывающий метод имеет те же два варианта снова. Как вы можете видеть, Exceptions может быть объявлен как throws полностью вверх по потоку вашей программы. Даже static void main(String[] args) может быть объявлен с помощью этих предложений throws, что в конечном итоге означает, что ваше приложение выйдет из строя, когда будет выдан один из объявленных Exception.


Посмотрите следующий пример:

/**
 * Throws a MyException.
 */
public static void methodThrowsException() throws MyException {
    throw new MyException();
}

/**
 * Calls methodThrowsException(), and handles the thrown MyException
 */
public static void myMethod() {
    try {
        methodThrowsException();
    } catch(MyException e) {
        /* Do something */
    }
}

/**
 * Calls methodThrowsException, but does not handle the thrown MyException.
 */
public static void mySecondMethod() throws MyException {
    methodThrowsException();
}

При вызове myMethod или mySecondMethod происходит следующее:

public static void main(String[] args) {
    myMethod(); /* No catching needed */
    try {
        mySecondMethod();
    } catch(MyException e){
        /* Catching needed */
    }
}

Как вы можете видеть, mySecondMethod только что перенесла проблему захвата MyException вызывающему абоненту.

Ответ 2

Предположим, что у вас есть методA, который вызывается методом methodB, который вызывается методом methodC и т.д....


Пример 1:

методА выдает исключение IOException.

Затем метод B должен либо бросить его, либо поймать его, что положит конец метанию. (Скажем, это бросает его).

Таким образом, метод C должен либо бросить, либо поймать его (опять же, пусть скажет, что это его выбрасывает).

Предположим, что методD фактически является основным методом. Опять же, вы должны бросить его или поймать. Если вы бросите его здесь, мы находимся в начальной точке, его некуда их выбросить, поэтому это остановит программу exeuting. Или вы можете поймать его.


Пример 2:

методА выдает исключение IOException.

методB снова должен его поймать или выбросить. На этот раз он ловит его.

methodC больше не нужно бросать или ловить его, потому что он рассматривается в методе B.

Ответ 3

Вероятно, вы должны проверить эту ссылку, чтобы понять, когда следует обрабатывать исключения (try-catch) и когда вы должны объявлять их (с предложением throws): http://docs.oracle.com/javase/tutorial/essential/exceptions/catchOrDeclare.html

Теперь, чтобы ответить на ваши вопросы -

Но разве не нужно ловить его в блоке try/catch?

Не всегда. Это зависит от типа исключения. Java имеет два типа исключений: Checked и Unchecked. И Error - это ситуация времени выполнения, из которой восстановление невозможно. Подробнее об этом здесь http://docs.oracle.com/javase/tutorial/essential/exceptions/

Для кода, который может выдавать проверенные исключения, вы MUST укажите один из следующих вариантов:

  • блок try-catch
  • throws предложение в объявлении метода

Для кода, который может вызывать непроверенные исключения, вы не вынуждаете компилятор обрабатывать их или объявлять. Хотя, вы можете сделать одно из них, если хотите.

Как я поймаю исключения в этом случае?

В вашем случае оба NotConnectedException и UnauthorizedException - это исключенные исключения. Таким образом, вы можете (но не вынуждены компилятором) написать блок try-catch в коде метода, или вы можете объявить их в предложении throws. Когда вы объявляете их в пункте throws, вызывающие из метода знают, что эти исключения MAY будут выбрасываться из него и планируют написать свой собственный try-catch для обработки исключений на их конце.

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

Как я уже упоминал, оба исключения не отмечены (унаследованы от RuntimeException), поэтому вам также не нужно делать это. Но вы можете сделать один из них.

Опять же, как я поймаю эти исключения, если я не буду писать блок try/catch?

нет. Вызывающий метод должен будет планировать обработку исключений со своим собственным try-catch.

Ответ 4

существует 3 вида исключений

  • Ошибка синтаксиса: ошибка компиляции
  • Логическая ошибка: -runtime
  • Ошибка выполнения: время выполнения (самая опасная ошибка)

здесь 1 и 2 могут быть решены вручную программистом.

тогда как при ошибке выполнения, например: - пользовательские входы 1/0, который является исключением, и 1000 строк кода сбрасываются в этот момент.

поэтому разработчики java подумали, как они удалят этот тип проблемы. Итак, они представили 2 вещи: -

  • бросает
  • try-catch наконец.

поэтому существует два типа исключений в java

  • Проверено (вам всегда нужен обработчик для отмеченного исключения)
  • Незарегистрированный

теперь позволяет говорить о том, как работает бросок: -

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

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

Ответ 5

Блоки try... catch (и даже finally:)) должны быть у метода вызывающего.
Например, метод вызывающего абонента:

public void handleTracks() {

 int limit = 100;
 try {
    List<String> trackIds = getTrackIds(trackIds);
 } catch (NotConnectedException ex) {
   System.err.println("No connection was established to the tacks system. Please perform login").
 } catch (UnauthorizedException ex) {
    System.err.println("The user is unauthorized to handle the track").
 }
}

Как вы можете видеть, существуют различные способы обработки различных типов исключений
Если необходимо, и вы используете JDK 7 и выше, вы можете заставить блок catch выглядеть следующим образом:

} catch (UnauthorizedException | NotConnectedException ex) {
    System.err.println("An error").
 }

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

Другим вариантом является, конечно, просто

 catch (Exception ex) {
    System.err.println("An error").
 }

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

Надеюсь, что это поможет.

Ответ 6

Думаю, я бы добавил еще один пример того, где я использовал настраиваемое исключение, и это может помочь понять, как используются исключения и как все сочетается. В программе калькулятора у меня есть ValidationException:

public class ValidationException extends Exception {

    public ValidationException(String msg){
        super(msg);
    }

}

У меня есть контроллер, который берет математическую сумму в виде строки. То есть это будет нечто вроде "(2 + 2) - 1 * 3".

Прежде чем вычислять ответ, он переходит в валидатор для проверки суммы, если он действителен (он делает такие вещи, как проверка, что в сумме нет букв, проверьте его не null, проверьте, нет ли двух математических операторов рядом друг с другом и т.д..).

public class Validator {

    public void check(String sum) throws ValidationException{
        checkForNull(sum);
        checkForLetters(sum);
    }

    private void checkForNull(String sum) throws ValidationException{
        if(sum==null || sum.equals("")){
            throw new ValidationException("You must enter a sum");
        }
    }


    private void checkForLetters(String sum) throws ValidationException {
        if(.......){
            throw new ValidationException("The sum cannot contain letters");
        }
    }

}

И тогда дескриптор контроллера выглядит так:

public void handle(){

    String sum = view.getSumFromUser();
    try{
        validator.check(sum);
        String answer = calculator.calculate(sum);
        view.outputResponse("The answer is " + answer);
    } catch (ValidationException ex){
        view.outputResponse(ex.getMessage());
    }

}

В этом последнем методе calculator.calculate(sum) только запускается, если validator.check(sum) завершается без каких-либо исключений.

Если есть исключение, пользователь получает сообщение об исключении.