[英]Function's return type can be Exception when it throws Exception
Let's say I have a function假设我有一个功能
private RuntimeException foo() {
return new RuntimeException();
}
and exception there is not thrown and it can be processed like并且没有抛出异常,可以像这样处理
throw foo();
or return value can be assigned to a variable或返回值可以分配给变量
RuntimeException e = foo();
But the function can be changed to但是函数可以改成
private RuntimeException foo() {
throw new RuntimeException();
}
and it still compiles and can be used like in previous examples or can just be called like foo();
它仍然可以编译并且可以像前面的例子一样使用,或者可以像foo();
一样被调用foo();
and Exception will be thrown.并且会抛出异常。
But why is it possible to specify RuntimeException
as a return type of a method that doesn't return it but throws it instead.但是为什么可以将RuntimeException
指定为不返回它而是抛出它的方法的返回类型。 Is there any connection between throw and return behavior in this case?在这种情况下,throw 和 return 行为之间是否有任何联系?
I've noticed that having Exception
(or more generally Throwable
) return type ensures that it will be thrown/returned in every decision branch like if/else statements.我注意到具有Exception
(或更普遍的Throwable
)返回类型确保它将在每个决策分支中抛出/返回,如 if/else 语句。 But is there any more practical usage or recommended of this?但是有没有更实际的用法或推荐呢?
Since throw
will make the execution of the method stop immediately and control is passed back to the caller, it doesn't matter what your method returns.由于throw
将使方法的执行立即停止并且控制权被传递回调用者,因此您的方法返回什么并不重要。 No matter what type you return, that type will not be returned, because you are throwing an exception (which indicates something wrong happened) on the first line.无论您返回什么类型,都不会返回该类型,因为您在第一行抛出异常(表示发生了错误)。
The compiler allows this because throwing an exception means something wrong happened, like the arguments are invalid, or the argument is null, and so on.编译器允许这样做,因为抛出异常意味着发生了错误,比如参数无效,或者参数为空,等等。 In such error conditions, the compiler does not expect the method to return a value normally.在此类错误情况下,编译器不希望该方法正常返回值。 It makes sense because obviously when something wrong happens, the method can't compute whatever it is that it was going to compute.这是有道理的,因为很明显,当发生错误时,该方法无法计算它要计算的任何内容。
So the phrase "all code paths must return a value" should really say "all code paths must return a value or throw a Throwable
".所以短语“所有代码路径必须返回一个值”应该真正说“所有代码路径必须返回一个值或抛出一个Throwable
”。
There is no relation between what a method returns and what it can throw.方法返回什么和它可以抛出什么之间没有关系。 and there are use cases where a method may both return and throw an exception.在某些用例中,方法可能既返回又抛出异常。
consider the following scenario: a method that is called to produce an application-specific exception:考虑以下场景:一个被调用以产生特定于应用程序的异常的方法:
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();
}
now guess what will happen if the argument itself is null
?现在猜猜如果参数本身为null
会发生什么? and the method does not even declares a throws
clause...并且该方法甚至没有声明throws
子句......
now, regarding having Exception as return value for the sake of ensuring that an exception is returned at every branch is just bad design.现在,为了确保在每个分支都返回异常而将 Exception 作为返回值是很糟糕的设计。 return value is not the mechanism to be used for throwing exception.返回值不是用于抛出异常的机制。 if you surround the entire method body with try-catch you will catch all exceptions from all branches.如果你用 try-catch 包围整个方法体,你将捕获所有分支的所有异常。
why is it possible to specify RuntimeException as a return type of a method that doesn't return it but throws it instead.为什么可以将 RuntimeException 指定为不返回它而是抛出它的方法的返回类型。 Is there any connection between throw and return behavior in this case?在这种情况下,throw 和 return 行为之间是否有任何联系?
It's possible to specify any type as a return type of any method.可以将任何类型指定为任何方法的返回类型。 There is no connection between return and throw behavior.返回和抛出行为之间没有联系。
I've noticed that having Exception (or more generally Throwable) return type ensures that it will be thrown/returned in every decision branch like if/else statements我注意到具有 Exception(或更一般的 Throwable)返回类型确保它会在每个决策分支中抛出/返回,如 if/else 语句
No, that's not the case.不,事实并非如此。 There is no way to "ensure [an Exception] will be thrown in every decision branch".没有办法“确保在每个决策分支中都会抛出[异常]”。 The only thing you can do is to state "this method may throw an Exception by using the throws
keyword:您唯一能做的就是声明“此方法可能会使用throws
关键字抛出异常:
public void mightThrowException() throws Exception {...}
but there's no guarantee that any exception will be thrown at all.但不能保证任何异常都会被抛出。
BTW, there are two types of exceptions: checked and unchecked.顺便说一句,有两种类型的异常:已检查和未检查。 Unchecked exceptions are subclasses of RuntimeException
;未经检查的异常是RuntimeException
子类; those do not need to be declared for your method.这些不需要为您的方法声明。 Checked exceptions do, so受检异常可以,所以
public void throwsIoException() {
throw new IOException();
}
is illegal because IOException
is a checked exception that needs to be declared with throws
.是非法的,因为IOException
是需要用throws
声明的已检查异常。
You mixed something up with your example.你把一些东西和你的例子搞混了。 Because when throwing an exception in a method the return type is not really considered, so instead of declaring the method like in your example.因为在方法中抛出异常时,并没有真正考虑返回类型,所以不要像在您的示例中那样声明方法。 you could also declare it like the following:你也可以像下面这样声明它:
public void foo(){
throw new RuntimeException();
}
or:或者:
public MyComplexType foo2(){
throw new RuntimeException();
}
The result is simply the same: An exception is thrown.结果是一样的:抛出异常。 The calling code just will look differently eg:调用代码看起来会有所不同,例如:
foo(); // throws RuntimeException
myOtherComputation(); // is never reached
or或者
MyComplexType type = foo2(); // throws RuntimeException
type.doSomething(); // is never reached
This behaviour can be useful when using for example a switch
statement in a method but throwing an error when entering the default branch:例如,当在方法中使用switch
语句但在进入默认分支时抛出错误时,此行为可能很有用:
public String foo(String string){
switch(string){
case "foo":
return "bar";
case "bar":
return "foo";
default:
throw new UnsupportedOperationException("Unknown string: '" + string + "'!");
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.