Интерфейс Java не объявляет никаких исключений. Как управлять проверенными исключениями реализации? - PullRequest
5 голосов
/ 29 апреля 2010

Допустим, у меня есть следующий интерфейс Java, который я не могу изменить:

public interface MyInterface {
  public void doSomething();
}

А теперь реализующий его класс выглядит так:

class MyImplementation implements MyInterface {
  public void doSomething() {
    try {
      // read file
    } catch (IOException e) {
      // what to do?
    }
  }
}

Я не могу восстановиться после того, как не прочитал файл.

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

Что я могу сделать?


Мы все согласны: интерфейс неисправен.

Решение, которое я выбрал

Я наконец решил написать MyVeryOwnInterface, который расширяет MyInterface и добавляет как часть сигнатуры ошибочных методов MyRuntimeException:

public interface MyVeryOwnInterface extends MyInterface {
  public void doSomething() throws MyRuntimeException;
}
class MyImplementation implements MyVeryOwnInterface {
  public void doSomething() throws MyRuntimeException {
    try {
      // read file
    } catch (IOException e) {
      throw new MyRuntimeException("Could not read the file", e);
    }
  }
}

Ответы [ 6 ]

8 голосов
/ 29 апреля 2010

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

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

3 голосов
/ 29 апреля 2010

Я бы скинул new IOError(e); и подал бы проблему на сопровождение интерфейса.

2 голосов
/ 29 апреля 2010

Если вы не можете восстановить, вам нужно выбросить и, таким образом, обернуть его в RuntimeException или Error и выбросить это.

public class Unchecked extends Error {

   private final Exception source;

   public Unchecked( Exception source) {
       this.source = source;
   }

   public String toString() {
       return "Unchecked Exception, Caused by: " + source;
   }

   public Exception getSource() {
       return source;
   }

   public static Unchecked wrap( Exception cause ) {
       return new Unchecked(cause);
   }
}
1 голос
/ 29 апреля 2010

Очевидно, что дизайнер интерфейса виноват в том, что не учел вероятность того, что doSomething () может завершиться ошибкой. В идеале он должен был либо позволить выбрасывать IOException (если он подозревал, что IO будет задействован), либо SomethingException (проверено), который вы могли бы использовать для обертывания вашего IOException.

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

Если все это не выполнено, вы можете выбрать молчание (возможно, запись, но не реагирование на проблему) или генерирование исключения RuntimeException, которое может прервать процесс.

0 голосов
/ 29 апреля 2010

Я бы предложил

throw new RuntimeException("while reading file " + fileName + "...", e);

Не проблема ли здесь в том, что интерфейс вообще не ожидает никаких проблем?

(и вы можете создать свое собственное исключение OurCompanyDomainException, расширяющее RuntimeException, чтобы его было легко отличить в коде на другой стороне интерфейса).

0 голосов
/ 29 апреля 2010

Я не думаю, что есть что-то еще, кроме объявления throws IOException в интерфейсе.Это просто природа Java-интерфейсов и проверенных исключений.

В вашем классе может быть другой метод (doSomethingDangerous), который выбрасывает IOException.Начиная с doSomething, вы просто вызываете doSomethingDangerous (обернутый в try / catch), а затем, где бы вы ни хотели быть осторожным, doingSomething вы вызываете doSomethingDangerous напрямую.

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