Можно ли сообщить компилятору, что метод всегда выдает исключение
Вообще говоря, компилятор 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();
}
}