Try/catch против бросков Exception

Эти операторы кода эквивалентны? Есть ли разница между ними?

private void calculateArea() throws Exception {
    ....do something
}

private void calculateArea() {
    try {
        ....do something
    } catch (Exception e) {
        showException(e);
    }
}

Ответ 1

Да, там огромная разница - последняя проглатывает исключение (показывая это, по общему признанию), в то время как первая будет распространяться. (Я предполагаю, что showException не реконструирует его.)

Итак, если вы вызовете первый метод и "сделайте что-нибудь", вы должны обработать исключение. Если вы вызовете второй метод и "сделаете что-нибудь", то вызывающий объект вообще не увидит исключение... что обычно плохо, если только showException не обработал исключение, исправлено все, что было не так, и что calculateArea достиг своей цели.

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

Ответ 2

Сначала throws Exception, поэтому вызывающему нужно обрабатывать Exception. Второй из них ловит и обрабатывает Exception внутренне, поэтому вызывающему абоненту не нужно выполнять обработку исключений.

Ответ 3

Да. Версия, объявляющая throws Exception, требует, чтобы вызывающий код обрабатывал исключение, а версия, которая явно обрабатывает его, не будет.

i.e., просто:

performCalculation();

против. перенося бремя обработки исключения вызывающему абоненту:

try {
    performCalculation();
catch (Exception e) {
    // handle exception
}

Ответ 4

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

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

Ответ 5

Существует один конкретный сценарий, когда мы не можем использовать броски, мы должны использовать try-catch. Существует правило: "Переопределенный метод не может вызывать лишнее исключение, кроме того, что бросает его родительский класс". Если есть дополнительное исключение, которое должно обрабатываться с помощью try-catch. Рассмотрим этот фрагмент кода. Существует простой базовый класс

package trycatchvsthrows;

public class Base {
    public void show()
    {
        System.out.println("hello from base");
    }
}

и его производный класс:

package trycatchvsthrows;

public class Derived extends Base {

    @Override
    public void show()   {
        // TODO Auto-generated method stub
        super.show();

        Thread thread= new Thread();
        thread.start();
        try {
            thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // thread.sleep(10);
        // here we can not use public void show() throws InterruptedException 
        // not allowed
    }
}

Когда нам нужно вызвать thread.sleep(), мы вынуждены использовать try-catch, здесь мы не можем использовать:

 public void show() throws InterruptedException

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

Ответ 6

Я предполагаю, что с помощью "идентичных" вы имеете в виду поведение.

Поведение функции может быть определено:

1) Возвращаемое значение

2) Исключенные исключения

3) Побочные эффекты (например, изменения в куче, файловой системе и т.д.)

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

Однако, если вы гарантируете, что "что-то" никогда не выдает исключение, тогда поведение будет идентичным (хотя компилятор потребует от вызывающего обработчика исключения в первой версии)

- редактировать -

С точки зрения дизайна API, методы в их контракте совершенно разные. Кроме того, бросать класс Exception не рекомендуется. Попробуйте бросить что-то более конкретное, чтобы позволить вызывающему лицу лучше обрабатывать исключение.

Ответ 7

Если вы выбрали исключение, дочерний метод (который переопределяет это) должен обрабатывать исключение

Пример:

class A{
public void myMethod() throws Exception{
 //do something
}
}

A a=new A();
try{
a.myMethod();
}catch Exception(e){
//handle the exception
}

Ответ 8

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

private void calculateArea() throws Exception {
    // Do something
}

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

private void calculateArea() {
    try {
        // Do something

    } catch (Exception e) {
        showException(e);
    }
}

Ответ 9

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

Ответ 10

private void calculateArea() throws Exception {
    ....do something
}

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

Тогда как во втором случае:

private void calculateArea() {
    try {
        ....do something
    } catch (Exception e) {
        showException(e);
    }
}

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

Try-catch - рекомендуемый подход.

ИМО,

  • Ключевое слово throws чаще всего используется с проверенными исключениями, чтобы убедить компилятор, но оно не гарантирует нормальное завершение программы.

  • Ключевое слово throws делегирует ответственность за обработку исключений
    вызывающая сторона (JVM или другой метод).

  • Ключевое слово throws требуется только для отмеченных исключений, для непроверенных исключений ключевое слово throws не используется.