Почему я не могу вызвать initCause () при создании экземпляра или выдаче исключения - PullRequest
0 голосов
/ 26 апреля 2018

Я не понимаю, почему я не могу просто initCause() в той же строке я создать экземпляр или выбросить исключение. Если я помещу его в одну и ту же строку, компилятор считает, что метод должен бросить бросаемый объект.

// All exceptions in the example are subclass of Exception class;
private static void throwException() throws BadCodeException {
    throw new BadCodeException("Actual cause");
}

private static void rethrowException() throws BadProgramException{
    try {
        throwException();
    } catch (BadCodeException e) {
        BadProgramException ex = new BadProgramException("Problem that occurred");
        ex.initCause(e);
        throw ex;
    } /* catch (BadCodeException e) { // Compiler tells about unhandled Throwable;
        throw new BadProgramException("Problem that occurred").initCause(e);
    } */

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

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

Потому что это подпись:

public synchronized Throwable initCause(Throwable cause);

Как видите, тип возвращаемого значения здесь Throwable;

Выполнение в одну строку равно:

// Throwable is not BadProgramException! It's wider type
private static void rethrowException() throws BadProgramException {
    try {
        throwException();
    } catch (BadCodeException e) {
        BadProgramException ex = new BadProgramException("Problem that occurred");
        Throwable throwable = ex.initCause(e);
        throw throwable;
    }
}

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

Выполнение в одну строку не меняет тип ссылки:

private static void rethrowException() throws BadProgramException {
    try {
        throwException();
    } catch (BadCodeException e) {
        BadProgramException ex = new BadProgramException("Problem that occurred");
        ex.initCause(e);
        throw ex; // Reference type is still BadProgramException and matches current signature
    }
}

В основном, вызов по одной линии может быть решен как:

private static void rethrowException() throws Throwable {
    try {
        throwException();
    } catch (BadCodeException e) {
        BadProgramException ex = new BadProgramException("Problem that occurred");
        throw ex.initCause(e);
    }
}

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

0 голосов
/ 26 апреля 2018

Как заявил khelwood, initCause имеет объявленный тип возврата Throwable (см. Документацию по API). Таким образом, если вы выбросите результат initCause, то (насколько может судить компилятор) ваш метод может выдать любой тип Throwable.

Чтобы ответить на ваш другой вопрос, обычный способ сделать цепочку исключений -

throw new BadProgramException("Problem that occurred", e);

и затем добавьте еще один конструктор в BadProgramException, если у него нет такого конструктора, который просто вызывает super с двумя аргументами.

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

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