总是如何检测死码

考虑下面的代码:

@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");
}

对我来说,println()永远不会被执行 - 因为对letsThrow()的调用总是会抛出一个异常。

因此我是

a)惊讶的是编译器不能告诉我“这是死代码”

b)想知道是否有一些编译器标志(或eclipse设置)会导致告诉我:你在那里得到了死代码。


死代码编译时错误由编译器定义,而不是由IDE定义。 虽然这是真的,但代码永远不会被执行,它不会违反任何Oracle Docs中不可达语句的规则。

从无法访问的语句

本节致力于对“可达”一词的精确解释。 这个想法是,从构造函数,方法,实例初始化程序或包含声明本身的语句的静态初始化程序开始,必须存在一些可能的执行路径。 分析考虑到了陈述的结构。 除了对while,do和do的特殊处理外,对于条件表达式具有常数值true的语句,流式分析中不考虑表达式的值。

这种情况下的规则与您创建的块是否可到达有关。 (iff =当且仅当)

如果它是可达的,则不是开关块的空白块可以正常完成。

如果其中的最后一条语句可以正常完成,非空块不是开关块就可以正常完成。

如果块是可到达的,则非空块中的第一条语句可以到达,而非非交换块。

如果前面的语句S可以正常完成,那么非空块中的每个其他语句S都不可以被访问。

letsThrow方法符合工作代码块的标准,并且通常在技术上完成 。 它抛出一个异常,但它完成。 在确定其实际使用中的代码块是否可达时,是否考虑它是否引发保证的异常。 在大多数情况下,死代码仅在涉及try / catch / returns(大部分规则)时才能找到。

考虑以下更简洁的版本:

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

除了努力使用覆盖工具之外,没有任何真正的计数器,但您示例中的亮点是每次运行代码时都会看到有保证的异常。


旨在进行全面的单元测试并测量测试的测试覆盖率。 死代码会很明显,因为没有你的测试导致它被执行。


声明你的方法返回一个可抛类型:

private final RuntimeException letsThrow() {
  throw new RuntimeException("guess you didnt see this one coming");
}

那么当你打电话时你可以抛出:

throw letsThrow();

现在,在调用letsThrow()任何代码都会被检测为死。

您可以通过检查使用您的静态分析工具不使用letsThrow()的返回值的情况来强制执行此操作。 例如,Google的errorprone为@CheckReturnValue注释提供了一个检查器,可以确保您使用结果。

(对于穷人的版本,搜索正则表达式^s*letsThrow(); )。

链接地址: http://www.djcxy.com/p/92089.html

上一篇: How can I detect dead code after always

下一篇: How to access the script/source history in RStudio?