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

Может ли кто-нибудь сказать мне, какие причины могут иметь исключения, а не быть совместимыми с предложениями "броски"

Например:

class Sub extends Super{

    @Override
    void foo() throws Exception{

    }

}

class Super{

    void foo() throws IOException{

    }
}

Исключение исключений несовместимо с предложением throws в Super.foo()

Ответы

Ответ 1

Без полного примера кода я могу только догадываться: вы переопределяете/реализуете метод в подклассе, но спецификация исключения для метода подкласса несовместима с (т.е. не подмножеством) класса суперкласса/интерфейса метод?

Это может произойти, если базовый метод объявлен вообще не выдавать исключений, или, например, java.io.IOException (который является подклассом java.lang.Exception, который пытается использовать ваш метод). Клиенты базового класса/интерфейса ожидают, что его экземпляры будут соответствовать контракту, объявленному базовым методом, поэтому выброс Exception из реализации этого метода приведет к разорению контракта (и LSP).

Ответ 2

Проверенные исключения предназначены для использования в ситуациях, когда метод может ожидать, что его вызывающий абонент будет готов к решению определенных проблем, которые могут возникнуть. Если вызывающим абонентам BaseFoo.Bar() не требуется иметь дело с FnordException, тогда метод DerivedFoo.Bar() не может ожидать, что его вызывающие стороны будут иметь дело с FnordException либо (так как многие из его вызывающих абонентов будут теми же, которые были не готовы BaseFoo.Bar() выбросить его).

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

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

Ответ 3

Чтобы исправить это, используйте RuntimeException

public T findById(long id) throws RuntimeException {
    try {
          return whatEver.create();
    } catch (SystemException e) {
          throw new RuntimeException(e);
    }
}

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

Ответ 4

Удостоверьтесь, что вы объявили о выбросе вашего интерфейса. Если вы это сделали, но проблема все еще сохраняется - попробуйте сохранить/перестроить проект.