考虑这个功能:
public boolean foo(){
System.exit(1);
//The lines beyond this will not be read
int bar = 1; //L1
//But the return statement is required for syntactically correct code
return false; //L2
//error here for unreachable code
//int unreachable = 3; //L3
}
Run Code Online (Sandbox Code Playgroud)
有人可以解释为什么L1和L2明显无法访问不会发出警告但L3会发出警告.
biz*_*lop 44
因为就编译器而言,System.exit()只是另一种方法调用.
它所做的是结束这个过程的事实只能从实现中找到(这是本机代码,而不是它有任何区别).
如果你必须把System.exit()你的代码(通常也最好避免它,除非你想返回0以外的代码),它应该是一个返回的方法void,main()例如.这样更好.
至于可达性,解释是相同的:return是Java语言的关键字,因此IDE使用的编译器或解析器可以return说明在执行语句之后理论上代码是不可能的.这些规则的定义在这里.
Jon*_*eet 13
Java编译器对此一无所知System.exit.就它而言,它只是一种方法 - 所以语句的结尾是可达的.
你这么说L1并且L2"明显无法到达"但这只是因为你知道是什么System.exit.语言没有 - 虽然它确实知道return语句的作用,但它知道L3实际上是不可达的.
我有时会想这将是能够声明的方法不仅是有用的void,但从来没有正常结束-它永远只是返回(虽然它可能会抛出异常).然后,编译器将能够使用该信息来使任何调用表达式的结束无法访问,从而防止出现此类问题.然而,这只是我周围的语言设计的梦想- Java的不具有类似的话,这将是一个非常糟糕的主意让编译器"知道"特定的JRE方法永远不会正常返回,当这个概念不能被表达直接在语言中.
相反,编译器受JLS第14.21节的规则约束,包括:
- 如果块可以访问,则非空块中不是交换块的第一个语句是可到达的.
- 如果S之前的语句可以正常完成,则非空交换块中的每个其他语句S都是可到达的.
...
如果表达式可以访问,则表达式语句可以正常完成.
(方法调用是表达式语句.)
然后从8.4.7节:
如果声明方法具有返回类型,则如果方法的主体可以正常完成,则会发生编译时错误(第14.1节).
并在14.1:
除非另有说明,否则如果所有表达式都在计算并且它执行的所有子语句正常完成,则语句正常完成.
因此,System.exit()就编译器而言,调用可以正常完成,这意味着方法的主体foo可以正常完成,从而导致错误.
从语言的角度来看,只有两种方法可以逃避当前的范围:return和throw.方法调用永远不会被认为是相同的方式,即使它们只包含代码行:
void method() {
throw new RuntimeException();
}
Run Code Online (Sandbox Code Playgroud)
更.理论上,任何方法调用都可能导致RuntimeException抛出.在这种情况下,编译器应该给你绝对任何不在try块内的方法调用的警告:
...
method(); // WARNING: may throw in theory
anotherMethod(); // WARNING: possible unreachable code, also may throw
anotherMethod2(); // WARNING: possible unreachable code, also may throw
// etc
...
Run Code Online (Sandbox Code Playgroud)
对于你的问题,逻辑是一样的.
我:"在退货声明之后可以执行任何事情吗?"
Java:"不."
我:"我可以在调用System.exit后执行任何操作吗?"
Java:"这是一种方法,我不知道它做了什么 - 它不是一个保留的关键字,据我所知,它不会影响程序流程"(它甚至可能不起作用(我不知道退出可以抛出异常(或它的未来变体)))