在总是抛出方法后如何检测死代码?

Gho*_*ica 7 java dead-code

考虑以下代码:

@Test 
public void testDeadCode() {
    letsThrow();
    System.out.println("will never be reached");
}

private final void letsThrow() {
    throw new RuntimeException("guess you didnt see this one coming");
}
Run Code Online (Sandbox Code Playgroud)

对我来说,println()似乎绝对不可能执行 - 因为对letsThrow()的调用将始终抛出异常.

我就是这样

a)惊讶于编译器无法告诉我"这是死代码"

b)想知道是否有一些编译器标志(或eclipse设置)会告诉我:你那里有死代码.

Com*_*ass 4

死代码编译时错误是由编译器而不是 IDE 定义的。虽然代码确实永远不会被执行,但它并不违反 Oracle 文档中有关无法访问语句的任何规则。

来自无法访问的语句

本节专门对“可达”一词进行精确解释。这个想法是,从包含语句的构造函数、方法、实例初始值设定项或静态初始值设定项的开头到语句本身,必须存在一些可能的执行路径。分析考虑了陈述的结构。除了对条件表达式为常量true的while、do、for语句进行特殊处理外,在流分析中不考虑表达式的值。

专门针对这种情况的规则与您创建的块是否可达有关。(当且仅当=当且仅当)

不是 switch 块的空块可以正常完成,前提是它是可访问的。

不是 switch 块的非空块可以正常完成,前提是其中的最后一条语句可以正常完成。

不是 switch 块的非空块中的第一个语句是可达的,当且仅当该块可达。

不是 switch 块的非空块中的所有其他语句 S 都是可达的,前提是 S 之前的语句可以正常完成。

letsThrow方法满足代码工作块的标准,并且在技术上可以正常完成。它抛出异常,但它完成了。在确定该代码块是否在实际使用中时,不考虑它是否抛出有保证的异常,而只考虑它是否可以到达。在大多数情况下,只有当涉及 try/catch/returns(这些是规则的大部分)时,才会发现死代码。

考虑以下更简洁的版本:

@Test 
public void testDeadCode() {
    System.exit(0);
    System.out.println("will never be reached");
}
Run Code Online (Sandbox Code Playgroud)

除了勤奋使用覆盖率工具之外,没有真正的对策,但示例中好的一面是每次运行代码时都会看到有保证的异常。