如果(null 检查)-else 和 try catch(NullPointerException)哪个更有效率?

19
以下三个函数中哪一个更有效率?
  public String getmConnectedDeviceName1() {
        if(null != mServerDevice) {
            return mServerDevice.getName();
        }
        else {
            return null;
        }
    }

  public String getmConnectedDeviceName2() {
        return mServerDevice == null ? null : mServerDevice.getName();
    }


  public String getmConnectedDeviceName3() {
        try{
            return mServerDevice.getName();
        }
        catch(NullPointerException e) {
            return null;
        }
    }

请回复具体可接受的逻辑。

3
没有适用的逻辑。为了测试空值而捕获异常是完全错误的做法。 - Simon
1
@Simon:问题不是对错的问题,而是关于效率的问题。仔细阅读问题。 - Shridutt Kothari
3
捕获异常是低效的,答案已经解释过了。但是,正确的实践几乎在所有情况下都比效率更重要。在这种情况下,就像大多数情况一样,正确的实践也是最高效的。 - Simon
6个回答

30

mServerDevicenull时,前者效率更高。当mServerDevice不为null时,两者效率相当。与null的比较只是比较两个32位整数,这是一种非常快速的操作。抛出异常的代价很大,因为需要创建新对象并填充堆栈跟踪。

三元运算符... ? ... : ...if(...) ... else ...语句的效率完全相同,因为它们都被转换为相同的字节码。


19

其实并不需要“反向”比较(这主要是C语言的遗留问题,在使用较差的编译器或忽略警告的情况下,拼写错误容易被忽视)-条件运算符可以使事情更简单:

return mServerDevice != null ? mServerDevice.getName() : null;

或者:

    return mServerDevice == null ? null : mServerDevice.getName();

使用if语句的版本在更复杂的情况下更适用。除非你调用的是一个无法避免地抛出NullPointerException的有缺陷的库,否则你应该永远不会捕获它。异常不应该被用于这种方式。它们用于检测编程错误和特殊的外部条件(如IO失败)。

与其他控制流构造相比,异常的开销相对较高。然而,不要将其推向另一个方向:有些人即使应该使用异常,也会避免它们,因为他们错误地认为这样做会增加开销。当适当使用时,异常不应该成为您性能配置文件的重要组成部分:如果发现它们占用了很多时间,则可能您的环境存在严重问题(例如,您一直试图连接到一个无法访问的数据库),或者您在滥用异常。

相对于捕获NullPointerException,这段代码既易读性更高,效率也更高。


@user000001:确实是这样——或者反转操作数的顺序。 - Jon Skeet
4
“这种方法不仅更易读,而且比捕获NullPointerException更高效”,这句话哪个部分没有表达哪个更高效?请注意,你很少应该以可读性为代价来微观优化代码。当你这样做时,你应该已经有测试,以便您可以轻松自己判断。 - Jon Skeet

2

我完全同意其他回答的观点。为了不重复,我只想告诉你,我现在正在介绍一个相当大的商业源代码,已经写了约3年时间,我没有看到使用你提到的 try-catch 方法的任何声明; 尽管有很多要检查 null 的地方 ;)


1

使用try-catch语句并不是更好的方法。

而且,try-catch会导致实例化新对象(异常)。

此外,if-else语句可以提高可读性。

因此,如果你有很多n == null的情况,我认为(n!= null)更快。

同时,n!=null是非常快速的结构。


0

在可以使用的情况下,请使用if-else。抛出和捕获异常可能很昂贵,应该用于处理错误情况(而不是用于逻辑分支)。


0
无论性能如何,我更喜欢使用if-else的形式。假设mServerDevice不为空,但在getName()调用过程中出现严重错误并抛出NullPointerException异常。基于异常的版本将会静默返回null,而不会记录错误日志。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接