Java 对字符串文本调用equals
我只是整理了一下我的代码,有这样一段:Java 对字符串文本调用equals,java,string,comparison,Java,String,Comparison,我只是整理了一下我的代码,有这样一段: String saving = getValue(); if(saving != null && saving.equals("true")){ // do something } 然后我想用另一种方法来避免检查null: if("true".equals(saving)){ // do something } 它确实有效,但是这样做安全吗?我的意思是字符串文本存储在公共池中,而由new创建的字符串对象则在堆中。但是常量池中
String saving = getValue();
if(saving != null && saving.equals("true")){
// do something
}
然后我想用另一种方法来避免检查null
:
if("true".equals(saving)){
// do something
}
它确实有效,但是这样做安全吗?我的意思是字符串文本存储在公共池中,而由new
创建的字符串对象则在堆中。但是常量池中的字符串也是对象,对吗
但是,尽管这样做会使代码更短,但似乎仍然不是正确的做法。这是安全的,正如您所看到的,这是避免空指针的一种好方法 您提到了对字符串使用
new
。许多java静态代码分析工具都建议始终在新字符串(“foo”)上使用文本代码>
编辑:
如果您愿意,您甚至可以使用:
根据,传递null
将返回false
这被称为yoda条件(在比较中将常量放在变量之前)可能被认为是不好的做法,可能对可读性差得多的人来说(比如我)
但有时使用yoda条件会使代码更“可理解”->
您不需要在代码前面加上额外的空检查,它可以有效地区分代码块和强烈禁止空的情况。将文本放在第一位的格式避免了潜在的NPE,并且对于“literal”.equals(null)
这是因为“literal”表达式的计算结果总是字符串对象(因此永远不会为null)和String。equals(obj)
检查另一个对象是否为null(通过asinstanceof
)。对象是对象-无需担心“堆”
在asnull中使用null保护是一种很好的做法。不允许使用equals(null)
:“equals方法在非null对象引用上实现等价关系”
以下是(适用于OpenJDK的):
这是非常安全和良好的做法。字符串“true”永远不会为null。因此,您永远不会将字符串与null进行比较。这段代码非常好只是为了确保这个问题有一组完全平衡的答案,我想发表不同的意见
我认为这种机制是愚蠢的
如果你有一个null
,你应该在它发生时就知道-隐藏它只会推迟它的发现。如果null
不是一个例外,用其他东西替换它
采用这种方法将通过所谓的防御性编程来强化代码,在这种编程中,您的错误会尽快被发现,而不是被掩盖,直到一切都崩溃为止
总之-NullPointerException
是您的朋友。您应该使用它来查找代码中的错误。一旦您确定null
不是异常,使用空对象(如Collections.emptySet()
)非常容易
出于习惯而使用尤达技术将不可避免地隐藏您无意隐藏的错误。不使用它将更早地暴露错误。对我来说,这足以证明永远不要使用它
对我来说-使用
if(saving != null && saving.equals("true")){
这意味着我实际上想允许储蓄
为空
,这是一种可以接受的情况-使用
if("true".equals(saving)){
只是以一种可能成为坏习惯的方式隐藏故意的选择。我不同意一些答案。有时你确实想知道你的变量是否为null
。这可能表明你的代码中发生了不好的事情,你可能想重新考虑你的逻辑
我不喜欢做if(“someString.equals(myString));
,因为我do想知道myString
是否为null
,并可能处理它或更改我的逻辑以防止类似情况
假设您有一个由于某些错误而计算错误的对象数组:
myStrings = {..., ..., null, null, ...};
然后,您希望对数组的对象执行一些操作,您将有:
if ("myString".equals(myObjArray[i])) { ... }
您不会得到NullPointerException
,您可能会认为您对数组中的所有对象执行了该操作,并且您永远不会知道由于隐藏了异常而计算错误。但是,如果您有:
if (myObjArray[i].equals("myString")) { ... }
您将获得一个NPE,您将知道阵列中有问题,您可能希望修复此问题或以另一种方式处理它。对不起,我不能同意这个问题
如果你首先使用常量,你就支持掩盖编程错误的结构,而且你也只能生成代码
要添加功能
修复编程错误
或者尝试支持结构以避免编程错误(例如
设计模式)
在上面,您有一个关于变量的弱断言
如果您必须处理来自其他模块的空值,您的任务是尽早将它们映射到域模型中的适当表示
在您自己的代码中,避免将null作为参数或返回值,因此不再需要任何null检查,建议的代码段也包括在内
你看,这个主题更多的是避免空值,而不是接受它来征服你的代码
if ("true".equals(saving))
是完美的“拯救”,由虚拟产品Sonarint和任何其他顾问推荐,这些顾问建立了您的主要要求您遵循的“深思熟虑”的规则
我说愚蠢,我的解释如下
如果您有以下代码,会发生什么
if (!saving.equals("true"))
{
if (saving.length() > 10)
{
// do something
}
}
您可以使用以下建议的代码
if (!"true".equals(saving))
{
if (saving.length() > 10)
{
// do something
}
}
但是,当您的代码部署到生产环境中时,如果保存变量尚未初始化且包含NULL,则程序将在length()
函数上崩溃
您必须更改代码以避免equals()上的NullPointerException
if ("true".equals(saving))
if (!saving.equals("true"))
{
if (saving.length() > 10)
{
// do something
}
}
if (!"true".equals(saving))
{
if (saving.length() > 10)
{
// do something
}
}
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
}
}