我正在审查一本最佳实践和推荐编码java的手册,我认为这是值得怀疑的。
Recomendation:
String variable;
"xx".equals(variable) // OK
variable.equals("xx") //Not recomended
因为防止出现不受控制的NullPointerException
这是真的吗?
答案 0 :(得分:24)
这是一种非常常见的技术,如果变量为null而不是抛出NullPointerException
,则会导致测试返回false。但我想我会有所不同,并说我不认为这是你应该遵循的建议。
可是:
NullPointerException
不一定是最糟糕的结果。假装一切都没关系,一直到最后都失败,这不是一个更好的选择。快速失败是好事。我个人不认为在所有情况下都应该要求使用这种技术。我认为应该由程序员根据具体情况做出判断。重要的是要确保以适当的方式处理空案例,以及如何执行此操作取决于具体情况。检查空值的正确处理可能是测试/代码审查指南的一部分。
答案 1 :(得分:10)
确实如此。如果您的示例中variable
为null
,
variable.equals("xx");
将抛出NPE,因为您无法在null对象上调用方法(equals
)。但
"xx".equals(variable);
只会返回false
而不会出错。
答案 2 :(得分:4)
实际上,我认为原来的建议是正确的。如果您使用variable.equals("xx")
,那么如果NullPointerException
为空,您将获得variable
。将常数字符串放在左侧避免了这种可能性。
这取决于你是否值得许多人认为是不自然习语的痛苦。
答案 3 :(得分:3)
这是Java(和C#)程序中常用的技术。第一种形式避免了空指针异常,因为在常量字符串.equals()
上调用"xx"
方法,该方法永远不为空。与null相比的非空字符串为false。
如果您知道variable
将永远不会为空(并且如果它永远为null,则您的程序以其他方式不正确),那么使用variable.equals("xx")
就可以了。
答案 4 :(得分:2)
确实,使用对象的任何属性都可以帮助您避免NPE。
但这就是为什么我们有例外,处理这类事情。
也许如果你使用“xx”.equals(变量),你永远不会知道变量的值是null还是不等于“xx”。 IMO最好知道你在变量中得到一个空值,所以你可以重新设置它,而不是忽略它。
答案 5 :(得分:0)
如果您需要检查null
,我发现这比可读性更好
if (variable != null && variable.equals("xx"))
。这更多的是个人偏好。
答案 6 :(得分:0)
你对检查的顺序是正确的 - 如果变量为null,在字符串常量上调用.equals将阻止NPE - 但我不确定我认为这是个好主意;我个人称之为“slop”。
Slop是指您没有检测到异常情况,但实际上创造了个人习惯以避免其被检测到的习惯。在一段时间内将null作为字符串传递最终会导致错误,这些错误可能很难找到。
slop的编码与“Fail fast fail hard”相反。
使用null作为字符串有时会产生一个很好的“特殊”值,但是你试图将它与某些东西进行比较这一事实表明你对系统的理解是不完整的(充其量) - 你越早发现这个事实越多越好。
另一方面,默认情况下使所有变量都是最终的,使用泛型并最小化所有对象/方法的可见性是减少污点的习惯。
答案 7 :(得分:0)
作为旁注,这里是一个设计模式,其中此代码建议可能没有任何区别,因为String(即Optional<String>
)永远不会因为来自设计模式的.isPresent()调用而为null:
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")));