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

Вообще говоря, компилятор Java не распространяет информацию о том, что метод "всегда" генерирует исключение и, следовательно, не обнаруживает, что все пути кода завершены.

(Это связано с тем, что компилятор Java компилирует каждый класс самостоятельно).

Это проблема, когда вы хотите написать что-то подобное.

public class ErrorContext {
    public void fatalISE(String message) {
        String context = "gather lots of information about the context of the error";
        throw new IllegalStateException(context +": " + message);
    }
}

public class A {
    public MyObject myMethod() {
        if (allIsGood()) {
            return new MyObject();
        }
        ErrorContext.fatalISE("all is not good");
    }
}

(т.е. своего рода "помощник подтверждения", который собирает контекстную информацию).

Поскольку компилятор будет жаловаться, что myMethod не всегда возвращает MyObject.

Насколько я знаю, нет конкретной аннотации, указывающей, что метод всегда выдает.

Ответы

Ответ 1

Простым обходным путем является использование метода fatalISE не исключение, но только его создание:

public class ErrorContext {
    public IllegalStateException fatalISE(String message) {
        String context = "gather lots of information about the context of the error";
        return new IllegalStateException(context +": " + message);
    }
}

public class A {
    public MyObject myMethod() {
        if (allIsGood()) {
            return new MyObject();
        }
        throw ErrorContext.fatalISE("all is not good");
    }
}

Таким образом, компилятор будет знать, что он не жалуется на отсутствие return. И забыть использовать throw маловероятно, именно потому, что компилятор обычно будет жаловаться.

Ответ 2

Трюк, который я использую, заключается в замене

public void fatalISE(String message) {
    String context = "gather lots of information about the context of the error";
    throw new IllegalStateException(context +": " + message);
}

с

public <T> T fatalISE(String message) {
    String context = "gather lots of information about the context of the error";
    throw new IllegalStateException(context +": " + message);
}

Затем в myMethod используйте:

public MyObject myMethod() {
   if (allIsGood()) {
        return new MyObject();
    }
    return ErrorContext.fatalISE("all is not good");
}

Он будет работать независимо от типа возвращаемого значения myMethod, включая примитивные типы. Вы все равно можете использовать fatalISE в методе void, просто не используя ключевое слово return.

Ответ 3

добавить

return null;

в конце. (он никогда не дойдет до него, но для молчания компилятора это должно сделать)

Ответ 4

Как насчет изменения условий if?

public MyObject myMethod() {
    if (!allIsGood()) {
        ErrorContext.fatalISE("all is not good");
    }
    return new MyObject();
}

Удачи!

Ответ 5

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

Чтобы сделать компиляцию кода, вы можете добавить return null; Как MouseEvent.

или лучше заменить его на throw new AssertionError(), которые предотвращают возврат нулевого значения, улучшают читаемость и гарантируют, что если кто-то изменит checkAndAlwaysThrowException(), он продолжит Всегда исключать исключение

public Object myMehtod() throws ExceptionType1, ExceptionType2 {
    //....
    checkAndAlwaysThrowException();
    throw new AssertionError("checkAndAlwaysThrowException should have throw exception");
}

public void checkAndAlwaysThrowException() throws ExceptionType1, ExceptionType2 {
    if (cond) {
        throw new ExceptionType1();
    } else {
        throw new ExceptionType2();
    }
}