Объявить-и-бросить против исключений-не-объявленных - PullRequest
9 голосов
/ 21 ноября 2008

В Java, в чем разница между методами-близнецами?

public void methodA() throws AnException {
    //do something
    throw new AnException();
}

public void methodA() {
    //do the same thing
    throw new AnException();
}

У меня есть интуиция, что это как-то связано с тем, чтобы быть хорошо разработанным методом (потому что я поместил methodA в интерфейс, объявил его так, как methodA * делает в своей реализации и получил предупреждение от Java, что "A * не может переопределить A, потому что A * не вызывает AnException ").

Это предположение верно?

Есть ли какие-либо тонкие коннотации в двух способах ведения дел?

Ответы [ 5 ]

13 голосов
/ 21 ноября 2008

Если AnException является проверенным исключением (другими словами, если оно не расширяет RuntimeException), methodA не будет компилироваться. Проверенные исключения всегда должны быть отклонены.

Если AnException является непроверенным исключением (если оно расширяет RuntimeException), то либо разрешается компилятором Java, либо любое из них интерпретируется эквивалентно средой исполнения Java. Метод A все еще, вероятно, все еще предпочтителен в этом случае по причинам документации. Javadoc для вашего метода покажет, что он может вызвать исключение AnException. Хорошо, если пользователи вашего метода знают, какие исключения им следует ожидать.

2 голосов
/ 22 марта 2009

Помимо хороших ответов других о компилируемости ваших методов, существует вопрос реализации интерфейсов и переопределения методов в суперклассах.

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

Допустим, вы используете какую-то структуру данных:

public abstract class AbstractBox {
  public abstract void addItem(Item newItem);
  public abstract void removeItem(Item oldItem);
}

У вас есть собственная реализация, но вы решили объявить исключения, которые не отображаются в исходной подписи:

public class MyBox extends AbstractBox {
  public void addItem(Item newItem) throws ItemAlreadyPresentException {...}
  public void removeItem(Item oldItem) throws NoSuchItemException {...}
}

Теперь давайте рассмотрим этот универсальный код, который обрабатывает объекты Box и получает экземпляр MyBox:

public void boxHandler(AbstractBox box) {
  Item item = new Item();
  box.removeItem(item);
}

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

Конечно, если вы обрабатываете исключения внутренне ... хорошо, компилятор будет более чем счастлив позволить вам удалить объявленные исключения из вашей подписи; -)

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

Ювал = 8 -)

1 голос
/ 22 марта 2009

Первый метод должен вызываться в блоке try catch или в объявлении метода throws AnException в противном случае компиляция завершится неудачей.

Второй не имеет такого ограничения

0 голосов
/ 21 ноября 2008

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

0 голосов
/ 21 ноября 2008

Во втором методе класс AnException должен быть подклассом RuntimeException, что означает, что объявление не является обязательным, и вызывающие методы не должны его обрабатывать. Примером RuntimeException является ArrayOutOfBoundException, представьте, если бы вы явно обрабатывали исключение (путем объявления бросков или с помощью блока try / catch) каждый раз, когда используете List.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...