14.21。无法访问的语句
如果由于无法访问而无法执行语句,则这是编译时错误。
本节专门对“可达”一词进行精确解释。这个想法是,从包含语句的构造函数、方法、实例初始化程序或静态初始化程序的开头到语句本身,必须有一些可能的执行路径。该分析考虑了语句的结构。除了特殊处理while、do和条件表达式为真值的语句外,流分析中不考虑表达式的值。
例如,Java 编译器将接受以下代码:
{ int n = 5; 而 (n > 7) k = 2; 尽管 n 的值在编译时是已知的,并且原则上它可以在编译时知道对 k 的赋值永远不会被执行。
本节中的规则定义了两个技术术语:
语句是否可达
语句是否可以正常完成
这里的定义允许一个语句只有在它可达时才能正常完成。
为了缩短对规则的描述,习惯上的缩写“iff”用于表示“当且仅当”。
如果在 break 目标内没有 try 语句的 try 块包含 break 语句,或者存在 try 语句的 try 块包含 break 语句并且这些 try 语句的所有 finally 子句都可以完成,则可到达的 break 语句退出语句一般。
此定义基于第 14.15 节中围绕“尝试转移控制权”的逻辑。
如果在 do 语句中没有 try 语句的 try 块包含 continue 语句,或者存在 try 语句的 try 块包含 continue 语句并且这些 try 语句的所有 finally 子句都可以完成,则 continue 语句继续 do 语句一般。
规则如下:
作为构造函数、方法、实例初始化程序或静态初始化程序的主体的块是可访问的。
一个不是 switch 块的空块可以正常完成,只要它是可达的。
一个不是 switch 块的非空块可以正常完成,前提是它的最后一条语句可以正常完成。
非空块中不是 switch 块的第一条语句是可到达的,前提是该块是可到达的。
如果 S 之前的语句可以正常完成,则非空块中不是 switch 块的所有其他语句 S 都是可访问的。
本地类声明语句可以正常完成,如果它是可访问的。
一个局部变量声明语句可以正常完成,只要它是可达的。
一个空语句可以正常完成,只要它是可达的。
如果以下至少一项为真,则带标签的语句可以正常完成:
包含的语句可以正常完成。
有一个可到达的 break 语句退出带标签的语句。
如果标记的语句是可访问的,则包含的语句是可访问的。
一个表达式语句可以正常完成,只要它是可达的。
一个 if-then 语句可以正常完成,只要它是可达的。
如果 if-then 语句可达,则 then 语句可达。
如果 then 语句可以正常完成或 else 语句可以正常完成,则 if-then-else 语句可以正常完成。
如果 if-then-else 语句是可达的,则 then-语句是可达的。
如果 if-then-else 语句可达,则 else 语句可达。
这种对 if 语句的处理,无论它是否有 else 部分,都是相当不寻常的。基本原理在本节末尾给出。
一个 assert 语句可以正常完成,只要它是可达的。
如果以下至少一项为真,则 switch 语句可以正常完成:
开关块为空或仅包含开关标签。
switch 块中的最后一条语句可以正常完成。
在最后一个 switch 块语句组之后至少有一个 switch 标签。
开关块不包含默认标签。
有一个可到达的 break 语句退出 switch 语句。
一个 switch 块是可达的,如果它的 switch 语句是可达的。
switch 块中的语句是可访问的,当且仅当它的 switch 语句是可访问的并且以下至少一项为真时:
它带有案例或默认标签。
在 switch 块中它前面有一条语句,并且前面的语句可以正常完成。
当以下至少一项为真时,while 语句可以正常完成:
while 语句是可访问的,并且条件表达式不是值为 true 的常量表达式(第 15.28 节)。
有一个可到达的 break 语句退出 while 语句。
如果 while 语句可访问且条件表达式不是值为 false 的常量表达式,则包含的语句是可访问的。
如果以下至少一项为真,则 do 语句可以正常完成:
包含的语句可以正常完成,并且条件表达式不是值为 true 的常量表达式(第 15.28 节)。
do 语句包含一个不带标签的可达 continue 语句,do 语句是包含该 continue 语句的最里面的 while、do 或 for 语句,并且 continue 语句继续该 do 语句,并且条件表达式不是常量表达式值为真。
do 语句包含一个带有标签 L 的可达 continue 语句,do 语句有标签 L,并且 continue 语句继续该 do 语句,并且条件表达式不是值为 true 的常量表达式。
有一个可到达的 break 语句退出 do 语句。
如果 do 语句是可访问的,则包含的语句是可访问的。
如果以下至少一项为真,则基本 for 语句可以正常完成:
for 语句可达,有条件表达式,且条件表达式不是值为 true 的常量表达式(第 15.28 节)。
有一个可到达的 break 语句退出 for 语句。
如果 for 语句可访问且条件表达式不是值为 false 的常量表达式,则包含的语句是可访问的。
增强的 for 语句可以正常完成,前提是它是可访问的。
break、continue、return 或 throw 语句无法正常完成。
如果包含的语句可以正常完成,则同步语句可以正常完成。
如果同步语句是可访问的,则包含的语句是可访问的。
如果以下两个都为真,则 try 语句可以正常完成:
try 块可以正常完成,或者任何 catch 块都可以正常完成。
如果 try 语句有 finally 块,那么 finally 块可以正常完成。
当 try 语句可达时,try 块是可达的。
如果满足以下两个条件,则可以访问 catch 块 C:
C的参数类型要么是未经检查的异常类型,要么是Throwable;或者 try 块中的某些表达式或 throw 语句是可访问的,并且可以抛出一个已检查的异常,其类型可分配给 catch 子句 C 的参数。
如果包含它的最里面的语句是可达的,则表达式是可达的。
有关表达式的正常和突然完成,请参见第 15.6 节。
try 语句中没有更早的catch 块A,使得C 的参数类型与A 的参数类型相同或子类。
如果 catch 块可达,则 catch 块的 Block 是可达的。
如果存在 finally 块,则当 try 语句可访问时,它是可访问的。