糟糕的java编译器优化?

Jav*_*ier 1 java

我有这段代码:

private void prepareContent() {
    log.info("do something");
    // success?
    boolean suc = false;
    suc = suc || uncompressToContent("file.tar.gz");
    suc = suc || uncompressToContent("file.tgz");
    for (int i = 0; i <= 9; i++) {
        suc = suc || uncompressToContent("dir/" + i + ".tgz");
        suc = suc || uncompressToContent("dir/" + i + ".tar.gz");
    }
    if (!suc) {
        log.error("unable to do something");
    }
}
Run Code Online (Sandbox Code Playgroud)

该函数对"file.tar.gz"和file.tgz"返回false.

问题是对uncompressToContent("dir/1.tgz")的调用返回true并且代码停止执行.其余代码未执行.

我不确定这是否是编译器中的错误.你怎么看?

补充:我忘了提到我需要执行对uncompressToContent的所有调用,并使用尽可能少的指令检查是否有任何返回true.

mik*_*era 10

编译器中没有错误.

只要suc设置为true(即从第一次uncompressToContent调用),则所有未来表达式将返回true 而不调用uncompressToContent.这是因为您使用的是短路布尔值或("||"),如果第一个参数为真,则不会评估第二个参数.

如果您想要进行所有呼叫,请使用普通或运算符("|")代替.


Uri*_*Uri 8

如果解压缩方法成功,则uncompress方法返回true,那么第一次发生这种情况时,suc将变为true.一旦suc成立,所有其他条件一旦suc被评估就会成立,因此OR的其他部分将不会被评估.因此,一旦至少一个成功,将不会尝试解压缩.

这称为短路并且是正确的行为,并且在大多数语言中是非常有用的属性.并且它也不是编译器优化,因为它是语言的已定义行为的一部分.

除了这个答案之外,我认为还有一些方法可以使这些代码更具可读性.首先,你确定你想要OR而不是AND吗?看起来你想要在一个文件没有正确压缩时立即退出,而不是因为正确解压缩而停止.

其次,更好的设计,恕我直言,将创建一个你要解压缩的所有文件名的列表,然后在该列表上执行for-each并执行所有的解压缩,这将使事情更具可读性.

第三,如果在大多数情况下解压缩成功,我认为异常处理比布尔返回值好得多.

这是我写这样的东西(我会把它分解成函数)

List<String> filenames = new ArrayList<String>();

this.collectFilenamesToDecompress(filenames) // Write one or more than one functions of this sort based on the semantics of your problem

try
{
   for(String filename: filenames)
   {
      uncompressFile(filename); // This will throw an exception if there is a failure
   } 
} catch(Exception e)
{
    // Announce that there was an error and you stopped decompressing because there was an error.
    // Return or quit
}
// If you got here, everything is great!
Run Code Online (Sandbox Code Playgroud)