用null检查java变量时哪个更有效?

时间:2018-10-18 10:32:06

标签: java

哪种方法是检查varName的null并调用方法名methodName2的最佳方法?

void methodName(String varName) {
    if (varName == null) {
        return;
    }
    methodName2();
}
//or 
void methodName(String varName) {
    if (varName != null) {
        methodName2();
    }
}
void methodName2() {
    // do the stuff
}

3 个答案:

答案 0 :(得分:2)

两种方法都需要对字符串varName进行一次检查,以查看其是否为null。因此,从性能的角度来看,两者应该几乎相同。话虽如此,我个人更喜欢第一个版本:

void methodName(String varName) {
    if (varName == null) {
        return;
    }

    methodName2();
}

我之所以这样,是因为null被明确处理为methodName()仅返回而没有做任何其他事情的情况。在您的第二个版本中,最终行为是相同的,但是从代码来看,它并不那么明显。此外,第二个版本还存在潜在的维护问题。假设有人继承了您的代码并需要添加功能:

void methodName(String varName) {
    if (varName != null) {
        methodName2();
    }

    // let's make the method do something else
}

由于null输入用例可以自由运行,因此有可能输入一些您不希望看到的代码。

答案 1 :(得分:1)

只有一种方法可以确保。使用jmh对它进行基准测试。

(我的直觉是JIT编译器将能够为性能相同的两个版本生成本机代码。做到这一点并不难...)

但是这里有一个更大的教训。在真实的程序中,这两种构造之间的性能(假设为!!)微小差异不太可能对整个应用程序的整体性能产生重大影响。的确,如果您不小心,可能会浪费大量的时间来优化无关紧要的内容。除非您已深入研究JIT编译器及其执行的优化,否则……您对即将发生的事情的直觉很可能是有缺陷的。

此外,您可能会发现“微”性能取决于您控制范围之外的细节:

  • JRE次要版本
  • 由于流水线差异,不同的L1和L2缓存大小等导致的不同芯片组的行为差异
  • 不同的物理内存和堆大小

您对一个JRE,芯片组等的微优化实际上可能会使更新的JRE,不同芯片组等的情况恶化/

最好的策略是将“微”优化留给JIT编译器。

如果您需要进行手动优化:

  1. 为整个应用程序(或库)创建一个现实的基准。
  2. 设置一些可量化的目标目标
  3. 使软件正常工作。
  4. 对它进行基准测试。如果达到目标,请停止!
  5. 分析它以查找热点。
  6. 选择一个新的热点进行优化。如果没有剩余时间可以花费很大的时间产生影响,请停止!
  7. 手动优化热点。
  8. 再次使用基准/个人资料。这有改善吗?如果不是,则退出优化。
  9. 重复。

答案 2 :(得分:0)

严格来说,答案取决于您所运行的JRE。如果JIT可以告诉您变量始终为(或永远不会)为null,则第二个版本更易于JIT完全修剪。更好的JRE仍然能够进行相同的优化。

但是我认为您是在问一个错误的问题。这种级别的微优化几乎永远不会有用。从根本上讲,在任何情况下,一项性能的提高都不会超过其可读性。您应该问自己,哪些可以更清楚地传达意图,而在一年后重新访问该代码时,哪些不太可能导致将来出现问题。