从我的理解下面我写了不应该编译的语句代码"我不可达"是后return
.
但是,编译绝对正常.
同样来自JLS:无法访问的语句,它不应该编译.
来自规范14.21无法到达的声明:
如果满足以下两个条件,则try语句可以正常完成:
try块可以正常完成,或者任何catch块都可以正常完成.
如果try语句有finally块,则finally块可以正常完成.
这里的try块无法正常完成,但catch块可以和finally块一样,所以我在这里很困惑
public class Test1 {
public static void main(String[] args) {
try {
return;
} catch (Exception e) {
System.out.println("catch");
} finally {
System.out.println("finally");
}
System.out.println("I am unreachable??!!!");
}
}
有人能帮我理解这种行为吗?
1> Eran..:
我相信这些是JLS 14.21的相关引用:
如果可以访问,则不是交换机块的空块可以正常完成.
非空交换块的非空块可以正常完成,如果其中的最后一个语句可以正常完成.
如果块可以访问,则非空块中不是交换块的第一个语句是可到达的.
如果S之前的语句可以正常完成,则非空交换块中的每个其他语句S都是可到达的.
所以你的
System.out.println("I am unreachable??!!!");
语句是可达的iff(这意味着"当且仅当")try语句可以正常完成,这导致下一个引用:
如果满足以下两个条件,则 try语句可以正常完成:
try块可以正常完成,或者任何catch块都可以正常完成.
如果try语句有finally块,则finally块可以正常完成.
由于您的catch
块可以正常完成并且您有一个finally
可以正常完成的块,因此该try
语句可以正常完成.因此System.out.println("I am unreachable??!!!");
,无论块return;
内的语句如何,其后面的语句都被认为是可达的try
.
请注意,or
在
try块可以正常完成,或者任何catch块都可以正常完成.
这要求try
块或至少一个catch
块正常完成.它不需要try
块和catch
块来正常完成.
最后,这种行为背后的逻辑:
编译器不应该分析try块是否可以抛出Exception
.原因是Exception
类层次结构包括已检查和未经检查的异常,并且未在throws
子句中声明未经检查的异常(如果您替换Exception
为某些已检查的异常,例如IOException
,编译器会抱怨您的try块从不抛出该异常,这会使该catch
块不可达).
因此,由于您有一个catch (Exception e)
可以正常完成的块,编译器会假定此catch块可以访问,因此整个try语句可以正常完成,即使该try
块无法正常完成.
finally块(如果存在)也必须能够正常完成,因为finally
块也被执行,因此如果它无法正常完成,则整个try语句无法正常完成.
我觉得chrylis到了那里,但他被打断了.
@chrylis你会在"InterruptedException"中添加什么?
我要添加一件事--`InterruptedException`.
回到实现`Thread.stop(Throwable)`时(除了在调用者处抛出异常),即使是`return`语句也可能因异常而失败.
@chrylis在Java中,术语*中断*用于通过`Thread.interrupt()`来发送信号,它只用"InterruptedException"结束阻塞操作(如`wait()`)或在显式查询时被检测到,即通过`Thread.interrupted()`.相反,通过`Thread.stop(...)`停止可能会强制导致任意代码位置的异常(包括那些试图处理这种异常的异常),这就是为什么它现在被弃用了很长时间甚至不支持最近的JVM用于其他throwables比`ThreadDeath`,它不是`Exception`的子类.
@chrylis不是,所有这一切都设置了*旗*,仅此而已.该旗帜如何被"消费"是一个不同的故事
2> Aman Chhabra..:
你有回报的尝试.
如果有异常并直接捕获该怎么办?因此,它在编译器方面并不可达,并且正在成功编译.
如果您也将获得回收,则编译将失败
另外,根据JLS 14.21:
如果在break目标中没有try块语句包含break语句,或者try语句的try块包含break语句,并且那些try语句的所有finally子句都可以完成,则可达到的break语句将退出语句一般.
当你在try和catch中返回时,请参阅下面的输出:
jshell> public class Test1 {
...> public static void main(String[] args) {
...> try {
...> return;
...>
...> } catch (Exception e) {
...> return;
...>
...> }
...>
...> System.out.println("I am unreachable??!!!");
...> }
...> }
| Error:
| unreachable statement
| System.out.println("I am unreachable??!!!");
| ^------------------------------------------^
如果在finally语句中返回并且编译失败,则会出现类似情况.
如果出现以下情况,将认为声明帖子尝试可达:
1) Try has a return statement with catch and finally not having return statement
2) Try does not have a return statement with catch having or not having return statement and finally not having return statement
3) Try, catch and finally not having return statement
3> Yashi Srivas..:
试图给出问题的更简化原因,代码是可达的,以防try块中发生异常.在这种情况下,控制进一步进入catch块,然后进入finally块.在finally块之后,将执行特定语句.
try {
return; //line 1
} catch (Exception e) {
System.out.println("catch"); //line 2
} finally {
System.out.println("finally"); //line 3
}
System.out.println("I am unreachable??!!"); //line 4
这意味着,有2个案例,因此有2个流程:
第1行 - >第3行 - >返回(如果没有异常)
第1行(发生异常) - >第2行 - >第3行 - >第4行(如果尝试获取异常)
只有当我们不保留任何控制权的可能性时,该线路才会无法到达.有两种方法:
从catch块返回
从finally块返回.
在这两种情况下,控件永远不会流向该行.
try {
return; //line 1
} catch (Exception e) {
System.out.println("catch"); //line 2
return; //return control
} finally {
System.out.println("finally"); //line 3
return; //or return from here
}
System.out.println("I am unreachable??!!"); //line 4
我希望现在能够清楚地了解问题的实际原因.
@YashiSrivastava因为`finally`块中的`return`会覆盖catch块中的任何返回,并且它也会吞下异常.请参阅[此问题](/sf/ask/17360801/)及其答案.
此外,它可以替换**'try`-block(或`catch`-block)中的`return`语句成功评估后返回的值** - 这可能会导致一些头痛:[见这个问题](/sf/ask/17360801/)
@jwenting:也许是SESE纯粹主义者和货物崇拜者.但不是"一般".如果您知道要返回什么,那么返回是最合适的事情.(有很好的理由不在"finally"块中返回,但它们与SESE关联较少,而且更多的是使代码撒谎.)