我只是整理了我的代码并且有这篇文章:
String saving = getValue();
if(saving != null && saving.equals("true")){
// do something
}
然后我想到了另外一种方法来摆脱对null
的检查:
if("true".equals(saving)){
// do something
}
这绝对有效,但这样安全吗?我的意思是字符串文字存储在公共池中,而由new
创建的字符串对象存储在堆上。但是常量池中的字符串也是对象,对吗?
但即使它使代码更短,它仍然是正确的做法。
答案 0 :(得分:22)
这是安全的 - 正如您所见,这是一种避免空指针的好方法。
您提到new
用于字符串。许多java静态代码分析工具将建议始终使用new String("foo");
上的文字。
编辑:
如果你愿意,你甚至可以使用:
if (Boolean.valueOf(saving)) {
...
}
根据docs,传递null
将返回false
。
答案 1 :(得分:21)
为了确保对这个问题有完全平衡的答案,我想发表不同意见。
我认为这种机制是愚蠢的。
如果你有一个null
,你应该尽快知道 - 隐藏它只会推迟它的发现。如果null
不是例外,请将其替换为其他内容。
采用这种方法将使用所谓的防御性编程强化您的代码,在这种情况下,您的错误会尽快被发现,而不是直到所有事情都崩溃为止。
总之 - NullPointerException
是你的朋友。您应该使用它来查找代码中的错误。一旦您确定Collections.emptySet()
不是例外,非常就可以轻松使用 Empty 对象,例如null
。
出于习惯而使用尤达技术将不可避免地隐藏您不想隐藏的错误。 不使用它会更早地暴露错误。对我而言,这是充分的论据,不使用它 - 永远。
给我 - 使用
if(saving != null && saving.equals("true")){
表示我实际上希望允许savings
成为null
并且这是可接受的情况 - 使用
if("true".equals(saving)){
只是以一种可能成为坏习惯的方式隐藏这种刻意的选择。
答案 2 :(得分:8)
它被称为yoda条件(在比较中将变量放在一个常量之前)可以被认为是不好的做法,也许对于那些可读性较差的人(比如我)。
但有时候使用yoda条件会使代码更“易于理解”->
你不需要在它前面加上额外的空值检查,它可以有效地区分代码块和强烈禁止null的情况。 / p>
答案 3 :(得分:8)
我不同意一些答案。有时您执行想知道您的变量是否为null
。这可能表明您的代码中发生了一些不好的事情,您可能想重新考虑您的逻辑。
我不喜欢if("someString".equals(myString));
,因为我做想要知道myString
是否null
并且可能会处理它或更改我的逻辑以防止像这样的情况。
想象一下,由于某些错误,你有一个被错误计算的对象数组:
myStrings = {..., ..., null, null, ...};
然后你想对数组的对象执行一些操作,你将拥有:
if("myString".equals(myObjArray[i])) { ... }
你不会得到NullPointerException
并且你会认为你对数组中的所有对象执行了操作..你永远不会知道你错误估计了它,因为你“隐藏”了这个例外。如果你这样做了:
if(myObjArray[i].equals("myString")) { ... }
你会得到一个 NPE ,你会知道数组中出现了问题......你可能想要解决这个问题或者用另一种方式处理它。
答案 4 :(得分:5)
if("true".equals(saving)){
// do something
}
这是非常安全和良好的做法。字符串“true”永远不会为null。因此,您永远不会将String与null进行比较。这段代码非常好
答案 5 :(得分:4)
首先放置文字的格式避免了潜在的NPE,"literal".equals(null)
总是假的。
这是因为“文字”表达式总是评估为String对象(因此永远不为空),String.equals(obj)
检查其他 object为null(通过asinstanceof
)。对象是一个对象 - 无需担心“堆”。
最好在an equals implementation中设置空值,因为null.equals(null)
不允许:“equals方法在非null上实现等价关系对象引用“
这是String.equals the source(对于OpenJDK):
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
// ..
}
return false;
}
答案 6 :(得分:2)
很抱歉,我无法就此问题达成一致。
如果您首先使用常量,则支持可以掩盖编程错误的结构。一个人应该只生成代码
最重要的是,你对这个变量有一个弱的断言。以下代码总是被强制检查空值。
如果您必须处理来自其他模块的空值,您的任务是尽早将它们映射到域模型中的正确表示。
在你自己的代码中,避免将null作为参数或返回值,因此不再需要任何空检查,包括建议的代码片段。
你知道,这个主题更多的是关于避免null而不是接受它来征服你的代码。
答案 7 :(得分:2)
if ("true".equals(saving))
完全是“保存”的,并由虚拟产品推荐,如SonarLint和建立此“良好”状态的任何其他顾问认为的规则,即您的主要要求是遵循。
我说是愚蠢的,下面是我的解释。
如果您有以下代码会怎样?
if (!saving.equals("true"))
{
if (saving.length() > 10)
{
// do something
}
}
您可以使用以下建议代码
if (!"true".equals(saving))
{
if (saving.length() > 10)
{
// do something
}
}
但是,当您的代码部署到生产环境中时,如果保存变量尚未初始化且包含NULL,则程序将在length()
函数上崩溃。
您已更改代码以避免在NullPointerException
函数上使用equals()
,但是您的程序将在NullPointerException
函数上返回另一个length()
!
好的反应是停止使用String文字提示,并分析代码以找到理想的解决方案,如以下示例所示。
if (saving != null)
{
if (!saving.equals("true"))
{
if (saving.length() > 10)
{
// do something
}
}
}
或
if (saving == null) saving = "";
if (!saving.equals("true"))
{
if (saving.length() > 10)
{
// do something
}
}
可能是冗长的,但是如果您要使用Java进行编程,那就是要付出的代价。
使用字符串文字equals()方法来避免NullPointerException
具有以下缺点
答案 8 :(得分:0)
不仅安全,而且还是解决此问题的首选方式。