一般来说,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。
据我所知,没有特定的注释来指示方法总是抛出。
答案 0 :(得分:35)
一个简单的解决方法是让你的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
是不太可能的,因为编译器通常会抱怨。
答案 1 :(得分:8)
我使用的技巧是替换
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的返回类型,包括基本类型。您仍然可以在void方法中使用fatalISE
,只需不使用return
关键字。
答案 2 :(得分:6)
如何扭转if条件?
public MyObject myMethod() {
if (!allIsGood()) {
ErrorContext.fatalISE("all is not good");
}
return new MyObject();
}
祝你好运!
答案 3 :(得分:5)
添加
return null;
最后。 (无论如何它永远不会到达那里,但这应该是编译器的沉默)
答案 4 :(得分:1)
您要尝试做的是声明一个函数永不返回,这是Java不知道该怎么做的。 Kotlin, for contrast, has a Nothing type。如果您声明函数返回“ Nothing”,则表示它永不返回。
Zorglub在上面的回答中,函数返回类型参数“ T”的类型参数是您在Java中最接近的。这是我最近写的东西,它记录一个字符串,然后使用相同的字符串引发异常:
/**
* Error logging. Logs the message and then throws a {@link RuntimeException} with the given
* string.
*
* @param tag String indicating which code is responsible for the log message
* @param msg String or object to be logged
*/
@CanIgnoreReturnValue
@SuppressWarnings("TypeParameterUnusedInFormals")
public static <T> T logAndThrow(String tag, Object msg) {
String s = msg.toString();
Log.e(tag, s);
throw new RuntimeException(s);
}
此代码使用Android的标准日志记录API,是我希望能够在可能需要值的任何地方使用的代码。我希望能够有一个lambda,其主体只是对此函数的调用。该解决方案效果很好,但是值得解释一些棘手的地方:
答案 5 :(得分:0)
我刚刚遇到了这个用例,但是使用的方法应该总是抛出2种或更多类型的异常。
要编译代码,您可以添加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();
}
}