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
)。对象是对象-无需担心“堆”

在as
null中使用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
            }
        }