假设我有一个功能
private RuntimeException foo() {
return new RuntimeException();
}
并且没有抛出异常,它可以像
一样处理throw foo();
或返回值可以分配给变量
RuntimeException e = foo();
但是该功能可以改为
private RuntimeException foo() {
throw new RuntimeException();
}
并且它仍然可以编译并且可以像之前的示例一样使用,或者可以像foo();
一样调用,并且将抛出异常。
但是为什么可以将RuntimeException
指定为不返回它的方法的返回类型,而是将其抛出。在这种情况下,抛出和返回行为之间是否有任何联系?
我注意到拥有Exception
(或更常见的Throwable
)返回类型可确保在每个决策分支中抛出/返回它,如if / else语句。但是有更实际的用法或推荐吗?
答案 0 :(得分:2)
由于throw
将使方法的执行立即停止并且控制权被传递回调用者,因此返回方法并不重要。无论你返回什么类型,该类型都将不返回,因为你在第一行抛出异常(表明发生了错误)。
编译器允许这样做,因为抛出异常意味着发生了错误,例如参数无效,或者参数为null,依此类推。在这种错误条件下,编译器不希望该方法正常返回值。这是有道理的,因为显然当出现错误时,该方法无法计算它将要计算的任何内容。
所以短语"所有代码路径必须返回一个值"应该说"所有代码路径必须返回一个值或抛出Throwable
"。
答案 1 :(得分:0)
方法返回的内容与它可以抛出的内容之间没有关系。 并且有一些用例可能会返回并抛出异常。
请考虑以下情形:调用方法以生成特定于应用程序的异常:
public Exception produceException(User u) {
if (u.id == null) return new UserNotFoundException();
if (u.name == null) return new UserDidNotCompleteRegistrationException();
if (u.email == null) return new UserDidNotVerifyEmailException();
}
现在猜猜如果参数本身是null
会发生什么?并且该方法甚至没有声明throws
子句......
现在,关于将Exception作为返回值以确保在每个分支返回异常只是糟糕的设计。返回值不是用于抛出异常的机制。如果用try-catch包围整个方法体,你将捕获所有分支的所有异常。
答案 2 :(得分:0)
为什么可以将RuntimeException指定为不返回它的方法的返回类型,而是将其抛出。在这种情况下,抛出和返回行为之间是否有任何联系?
可以将任何类型指定为任何方法的返回类型。返回和抛出行为之间没有联系。
我注意到拥有Exception(或更普遍的Throwable)返回类型可确保在每个决策分支中抛出/返回它,如if / else语句
不,事实并非如此。没有办法确保[每个决策分支中都会抛出[异常]"。您唯一能做的就是声明"此方法可能使用throws
关键字抛出异常:
public void mightThrowException() throws Exception {...}
但是不保证会抛出任何异常。
顺便说一下,有两种类型的例外:已选中和未选中。未经检查的例外是RuntimeException
的子类;那些不需要为您的方法声明。检查过的例外,所以
public void throwsIoException() {
throw new IOException();
}
是非法的,因为IOException
是需要使用throws
声明的已检查异常。
答案 3 :(得分:0)
你把一些东西与你的例子混在一起。因为在方法中抛出异常时,实际上并未考虑返回类型,因此不会像示例中那样声明方法。你也可以声明如下:
public void foo(){
throw new RuntimeException();
}
或:
public MyComplexType foo2(){
throw new RuntimeException();
}
结果完全相同:抛出异常。调用代码看起来会有所不同,例如:
foo(); // throws RuntimeException
myOtherComputation(); // is never reached
或
MyComplexType type = foo2(); // throws RuntimeException
type.doSomething(); // is never reached
当在方法中使用例如switch
语句但在输入默认分支时抛出错误时,此行为非常有用:
public String foo(String string){
switch(string){
case "foo":
return "bar";
case "bar":
return "foo";
default:
throw new UnsupportedOperationException("Unknown string: '" + string + "'!");
}
}