我正在审查一份Java编码最佳实践和推荐手册,但我认为其中有些内容令人怀疑。
建议:
String variable;
"xx".equals(variable) // OK
variable.equals("xx") //Not recomended
这是因为可以防止未经控制的NullPointerException的出现。
这是真的吗?
我正在审查一份Java编码最佳实践和推荐手册,但我认为其中有些内容令人怀疑。
建议:
String variable;
"xx".equals(variable) // OK
variable.equals("xx") //Not recomended
这是因为可以防止未经控制的NullPointerException的出现。
这是真的吗?
这是一种很常见的技巧,如果变量为 null 则会返回 false 而不是抛出 NullPointerException
异常。但我认为我有些与众不同,不会将此视为您始终应遵循的建议。
但:
NullPointerException
不一定是最糟糕的结果。假装一切正常并一直运行,直到最终失败并不是一个更好的选择。快速失败是好的。个人而言,我并不认为在所有情况下都需要使用此技术。我认为应该根据具体情况由程序员自行判断。重要的是确保以适当的方式处理了 null 情况,如何处理取决于情况。检查 null 值的正确处理可能是测试/代码审查指南的一部分。
没错,如果在你的例子中 variable
是 null
的话,
variable.equals("xx");
会抛出NPE(NullPointerException)异常,因为你不能在一个空对象上调用一个方法(equals
)。但是
"xx".equals(variable);
如果没有错误,将只返回false
。
实际上,我认为原始建议是正确的。如果您使用variable.equals("xx")
,那么如果variable
为空,您将获得一个NullPointerException
。把常量字符串放在左边可以避免这种可能性。
这取决于您是否认为这种防御措施值得使用许多人认为不自然的习惯用语所带来的痛苦。
这是Java(和C#)程序中常用的技巧。第一种形式避免了空指针异常,因为.equals()
方法是在常量字符串"xx"
上调用的,该字符串永远不会为空。与null进行比较的非空字符串是false。
如果您知道variable
永远不会为空(如果它为空,则您的程序以某种其他方式是不正确的),那么使用variable.equals("xx")
就可以了。
确实,以这种方式使用对象的任何属性都可以帮助您避免NPE。
但这就是为什么我们有异常来处理这些事情。
也许如果您使用 "xx".equals(variable),您永远不会知道变量的值是null还是不等于 "xx"。在我看来,最好知道您的变量正在获取null值,这样您就可以重新分配它,而不是忽略它。
你对检查的顺序是正确的——如果变量为空,调用字符串常量上的.equals将防止NPE——但我不确定我认为这是一个好主意;个人称之为“马虎”。
马虎是指您没有检测到异常情况,但实际上创建了习惯以个人避免其检测。长时间传递空值作为字符串最终会导致可能很难找到的模糊错误。
编写马虎代码与“快速失败”相反。
将null用作字符串有时可以成为一个很好的“特殊”值,但是您试图将其与某些内容进行比较表明您对系统的理解不完整(至少如此)——您越早发现这一事实,就越好。
另一方面,默认情况下使所有变量都是final,使用泛型并最小化所有对象/方法的可见性是减少马虎的习惯。
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")));
null
,我认为这比if (variable != null && variable.equals("xx"))
更易读。这更多是个人偏好的问题。