Подтвердить что ты не робот

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

Какова наилучшая практика, когда вам нужно создать исключение, которое не было определено в интерфейсе, который вы реализуете?

Вот пример:

public interface Reader
{
    public abstract void read() throws IOException;
}

public class CarrotReader implements Reader
{
    public void read() throws IOException {}
}

public class CupcakeReader implements Reader
{
    public void read() throws IOException, CupcakeException {}
}

В этом случае у вас есть особое исключение, возникающее при чтении кексов, поэтому вы хотите создать исключение, связанное с этим. Однако Reader не определяет этот тип исключения в своем интерфейсе, так что вы делаете? Кроме того, нет смысла добавлять CupcakeException в предложение throws в интерфейсе Reader, потому что этот тип исключения специфичен для CupcakeReader. Одним из способов этого является чтение чтения Reader таким образом, что он генерирует некоторый родительский тип, например Exception, но затем вы теряете контекст для исключения. Что вы должны делать в этой ситуации? Спасибо!


Еще одна интересная ситуация, которая возникла, связана с интерфейсом, над которым вы не контролируете. В этом случае, что является лучшим способом указать, что проблема возникла?

Для иллюстративных целей, вот еще один пример:

public interface Reader
{
    public abstract void read();
}

public class CupcakeReader implements Reader
{
    public void read() throws CupcakeException {}
}

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

4b9b3361

Ответ 1

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

... catch(CupcakeException e) {
   throw new IOException("The sky is falling", e);
 }

Ответ 2

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

Ответ 3

Исключение является частью интерфейса. Определите родительский родитель для всех ваших исключений в интерфейсе, если вы можете переопределить интерфейс.

Вы также можете сделать CupcakeException дочерним элементом IOException.

Ответ 4

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

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

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

Итак, вместо:

Value value = reader.read();

Вы заставляете его делать это:

Value value = null;
try {
    value = reader.read();
} catch (Exception e) {
    // now what??
}

value.doSomething();   // potential NPE here

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

EDIT:

Я удивлен отрицательным рейтингом. Есть люди, которые все еще считают, что проверенные исключения велики? Если да, то есть некоторые ссылки, почему вы не должны использовать проверенные исключения:

  • Никакая современная структура не использует проверенные исключения (Spring, EJB3 и т.д.)
  • Статья с примерами кода здесь
  • StackOverflow тема
  • Эффективная Java (разделы 58 и 59) - здесь

Ответ 5

Возможно, вы могли бы создать абстрактный класс ReaderSpecificException, поместить его в интерфейс и subclass CupcakeException из этого абстрактного класса.

Ответ 6

Если вы создаете более высокое абстрактное исключение, которое работает как базовый класс для CupCakeException, вы не привязываете интерфейс Reader к конкретной реализации, как если бы вы добавили CupCakeException к интерфейсу Reader. Если вы не допустили, чтобы один Exception наследовал от другого, в классе исключений существует конструктор, который принимает бросаемый в качестве второго аргумента, такой как Thorbjørn Ravn Andersen allready показал в своем примере с коротким кодом. Это позволяет вам генерировать более абстрактное исключение, и каждая часть вашего кода, которая должна знать больше, а затем просто "есть ошибка", может искать причину более высокого исключения.