为什么编译器构建在某些情况下返回无法访问的代码

时间:2018-02-16 10:31:00

标签: java android android-studio javac

如果我写

private void check(){
   if(true)
      return;

   String a = "test";
}

以上代码正常,但如果我写

private void check(){
   return;

   String a = "test";
}

Android Studio中的编译器/ gradle并不会让它通过,即使它是相同的,并且它表示示例2中返回后的代码无法访问。

我对此没有任何问题,但我很想知道为什么?

4 个答案:

答案 0 :(得分:1)

javac编译器做了很少的优化,所以它根本没有“看到”if(true)始终是true(但你应该收到警告);但C1 / C2 JIT编译器将 - 所以代码只是return,没有if语句。

答案 1 :(得分:1)

这可以通过Java语言规范的Unreachable Statements部分来解释。

有很多规则,有一个有趣的特例。这是一个编译时错误:

while (false) {
    // this code is unreachable
    String something = "";
}

虽然不是这样:

if (false) {
    // this code is considered as reachable
    String something = "";
}

给出的原因是允许某种条件编译,例如:

static final boolean DEBUG = false;
...
if (DEBUG) { x=3; }

所以在你的情况下:

private void check(){
    if(true)
        return;

    // NO compilation error
    // this is conditionnal code
    // and may be omitted by the compiler
    String a = "test";
}
由于特殊if处理,

不是错误,因此不接受使用while

private void check(){
    while(true)
        return;

    // "Unreachable statement" compilation error
    String a = "test";
}

这也是错误的:

private void check(){
    if(true)
        return;
    else
        return;

    // "Unreachable statement" compilation error
    String a = "test";
}

答案 2 :(得分:0)

当它尝试编译时,它会构建一个抽象语法树。在第一种情况下,'true'是一个匿名变量,因此将添加两个分支,即使只有一个分支是可能的。在第二种情况下,只有一个可能的分支要创建,它永远不会到达终点。

答案 3 :(得分:0)

区别在于这些需要两种不同的分析来确定行为。第一个例子需要语义分析,而后者需要语法分析。编译器是语法方面的专家;这就是他们要做的事情。但是,他们经常在语义上挣扎。执行静态语义分析需要编译器编写者花费更多精力,并且通常很难得到正确的。