Java中,"xx".equals(variable)比variable.equals("xx")更好,对吗?

20

我正在审查一份Java编码最佳实践和推荐手册,但我认为其中有些内容令人怀疑。

建议:

String variable;

"xx".equals(variable) // OK

variable.equals("xx") //Not recomended

这是因为可以防止未经控制的NullPointerException的出现。

这是真的吗?


3
如果你正在撰写技术手册,那么你需要担心的语法问题比这个小小的编码注意事项要更大。 - Zak
6
@ Zak,那并不是很相关。你怎么知道手册会用英语编写?也许Xerg能流利地使用其他语言,并且正在用那种语言创建手册。所有回答的人都成功地理解了这个问题的关键点。 - Peter Recore
1
我并不是在写手册,只是在检查。请原谅我的英语,我更擅长阅读而不是写作。 - Xerg
8个回答

29

这是一种很常见的技巧,如果变量为 null 则会返回 false 而不是抛出 NullPointerException 异常。但我认为我有些与众不同,不会将此视为您始终应遵循的建议。

  • 我认为所有 Java 程序员都应该知道它,因为它是一个常见的习惯用语。
  • 这也是一种使代码更简洁的有用技术(您可以同时处理 null 和非 null 情况)。

但:

  • 它会使您的代码更难阅读:"如果蓝色是天空..."
  • 如果您刚刚在上一行检查了参数是否为 null,则它是不必要的。
  • 如果您忘记测试 null 并且有人确实使用了您未预期的 null 参数,则 NullPointerException 不一定是最糟糕的结果。假装一切正常并一直运行,直到最终失败并不是一个更好的选择。快速失败是好的。

个人而言,我并不认为在所有情况下都需要使用此技术。我认为应该根据具体情况由程序员自行判断。重要的是确保以适当的方式处理了 null 情况,如何处理取决于情况。检查 null 值的正确处理可能是测试/代码审查指南的一部分。


2
它会让你的代码难以阅读:“如果蓝色是天空……”——也被称为尤达条件。-http://en.wikipedia.org/wiki/Yoda_conditions - chrismarx

11

没错,如果在你的例子中 variablenull 的话,

variable.equals("xx");

会抛出NPE(NullPointerException)异常,因为你不能在一个空对象上调用一个方法(equals)。但是

"xx".equals(variable);

如果没有错误,将只返回false


@Tom:嗯,也许吧。我遇到过应该是错误的情况,也遇到了很多其他情况,那时它不应该是错误的。我其实同意Mark Byers的看法,根据具体情况来评估是有意义的。 - David Z

4

实际上,我认为原始建议是正确的。如果您使用variable.equals("xx"),那么如果variable为空,您将获得一个NullPointerException。把常量字符串放在左边可以避免这种可能性。

这取决于您是否认为这种防御措施值得使用许多人认为不自然的习惯用语所带来的痛苦。


1
个人而言,我觉得“Yoda版本”很难读,但它确实避免了空指针异常。另一种选择是's!= null && s.equals(“xx”)',这需要更多的输入并需要额外的几纳秒来进行额外的比较。 - Jay

3

这是Java(和C#)程序中常用的技巧。第一种形式避免了空指针异常,因为.equals()方法是在常量字符串"xx"上调用的,该字符串永远不会为空。与null进行比较的非空字符串是false。

如果您知道variable永远不会为空(如果它为空,则您的程序以某种其他方式是不正确的),那么使用variable.equals("xx")就可以了。


3

确实,以这种方式使用对象的任何属性都可以帮助您避免NPE。

但这就是为什么我们有异常来处理这些事情。

也许如果您使用 "xx".equals(variable),您永远不会知道变量的值是null还是不等于 "xx"。在我看来,最好知道您的变量正在获取null值,这样您就可以重新分配它,而不是忽略它。


1

你对检查的顺序是正确的——如果变量为空,调用字符串常量上的.equals将防止NPE——但我不确定我认为这是一个好主意;个人称之为“马虎”。

马虎是指您没有检测到异常情况,但实际上创建了习惯以个人避免其检测。长时间传递空值作为字符串最终会导致可能很难找到的模糊错误。

编写马虎代码与“快速失败”相反。

将null用作字符串有时可以成为一个很好的“特殊”值,但是您试图将其与某些内容进行比较表明您对系统的理解不完整(至少如此)——您越早发现这一事实,就越好。

另一方面,默认情况下使所有变量都是final,使用泛型并最小化所有对象/方法的可见性是减少马虎的习惯。


0
作为附注,这里有一个设计模式,在这种情况下,代码建议可能不会有任何区别,因为String(即Optional<String>)由于设计模式中的.isPresent()调用而永远不会为空:
Optional<String> gender = Optional.of("MALE");
if (gender.isPresent()) {
    System.out.println("Value available.");
} else {
    System.out.println("Value not available.");
}
gender.ifPresent(g -> System.out.println("Consumer: equals: " + g.equals("whatever")));

0
如果您需要检查是否为null,我认为这比if (variable != null && variable.equals("xx"))更易读。这更多是个人偏好的问题。

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