Исключение проглатывается окончательно - PullRequest
8 голосов
/ 17 января 2011
static int retIntExc() throws Exception{
    int result = 1;
    try {
        result = 2;
        throw new IOException("Exception rised.");
    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println(e.getMessage());
        result = 3;
    } finally {
        return result;
    }
}

Мой друг является разработчиком .NET и в настоящее время мигрирует на Java, и он задает мне следующий вопрос об этом источнике. Теоретически это должно throw IOException("Exception rised."), а весь метод retIntExc() должен throws Exception. Но ничего не происходит, метод возвращает 2.

Я не проверял его пример, но думаю, что это не ожидаемое поведение.

РЕДАКТИРОВАТЬ: Спасибо за все ответы. Некоторые из вас игнорируют тот факт, что метод называется retIntExc, что означает, что это всего лишь некоторый тестовый / экспериментальный пример, показывающий проблему в механике броска / ловли. Мне не нужно было исправлять, мне нужно было объяснить, почему это происходит.

Ответы [ 7 ]

16 голосов
/ 17 января 2011

Вот почему вы не можете вернуться из блока finally в C #:)

Это абсолютно поведение, изложенное в Спецификации языка Java. Это указано в разделе 14.20.2 .

Если блок finally завершается преждевременно по причине S, то оператор try завершается преждевременно по причине S (и выброс значения V отбрасывается и забывается).

Возвращение является одним из примеров внезапного завершения; если блок finally выдает исключение, то также завершается внезапно, теряя исходное исключение.

Приведенная выше цитата была взята из этого вложенного набора пунктов, оставляя без внимания опции, которые здесь не применимы:

  • Если выполнение блока try завершается внезапно из-за выброса значения V, то есть выбор:
    • Если тип времени выполнения V не может быть назначен параметру какого-либо предложения catch оператора try, тогда выполняется блок finally. Тогда есть выбор:
      • Если блок finally завершается преждевременно по причине S, то оператор try завершается преждевременно по причине S (и выброс значения V отбрасывается и забывается).
3 голосов
/ 17 января 2011

Будет возвращено 2, потому что

finally всегда выполнять

2 голосов
/ 17 января 2011

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

Удаление блока finally вокруг возврата даст желаемое поведение.

2 голосов
/ 17 января 2011

Блок finally выполняется независимо от того, какое исключение выдается.Он не просто выполняется после того, как исключения перехвачены объявленными вами блоками catch.Выполняется после блока try и перехвата исключений, если таковые имеются .Если ваш метод выдает исключение, он не может ничего вернуть, если вы не проглотите его в своем методе и не вернете result.Но вы не можете иметь и то и другое.

Кроме того, если у вашего метода нет другого кода, ArrayIndexOutOfBoundsException также никогда не встретится.

0 голосов
/ 17 января 2011

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

static int retIntExc() throws Exception{
        int result = 1;
        try {
            result = 2;
            throw new IOException("Exception rised.");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println(e.getMessage());
            result = 3;
        } finally {
            // do something
        }
        // it gets here only when exception is not thrown
        return result;
    }
0 голосов
/ 17 января 2011

Я не понимаю, почему это не будет ожидаемым поведением.К концу этого блока кода результат равен 2.

static int retIntExc() throws Exception{
        int result = 1;
        try {
            result = 2;

Затем вы генерируете исключение, но ваш блок catch перехватывает исключения другого типа, поэтому ничего не выполняется.

        throw new IOException("Exception rised.");
    } catch (ArrayIndexOutOfBoundsException e) {
          ...
    }

Гарантируется, что блок finally будет выполнен, поэтому последний шаг должен вернуть 2.

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

0 голосов
/ 17 января 2011

Класс IOException не является потомком класса ArrayIndexOutOfBoundsException , поэтому часть catch никогда не будет выполнена.

Если вы измените это, он вернет 3.

static int retIntExc() throws Exception{
        int result = 1;
        try {
            result = 2;
            throw new ArrayIndexOutOfBoundsException ("Exception rised.");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println(e.getMessage());
            result = 3;
        } finally {
            return result;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...