当 “” == s 为假但 “”.equals( s ) 为真时在哪些其他情况下:

2022-09-01 07:21:39

编辑感谢您的及时回复。请看看真正的问题是什么。这次我把它变得大胆了。

我确实理解 == 和 .equals 之间的区别。所以,这不是我的问题(我实际上为此添加了一些上下文)


我正在对空字符串执行下面的验证:

if( "" == value ) { 
    // is empty string 
} 

过去,当从数据库获取值或从另一个节点反序列化对象时,此测试失败了,因为两个字符串实例确实是不同的对象引用,尽管它们包含相同的数据。

因此,解决这些情况的方法是

if( "".equals( value ) ) {
   // which returns true for all the empty strings
}

我对此很好。这是显而易见的。

今天,这种情况再次发生,但它让我感到困惑,因为这次应用程序是一个非常小的独立应用程序根本不使用网络,因此不会从数据库获取新字符串,也不会从另一个节点反序列化。

所以问题是:


在哪些其他情况下:

"" == value // yields false 

"".equals( value ) // yields true

对于本地独立应用程序?

我很确定新的String()没有在代码中使用。

字符串引用可能是“”的唯一方法是因为它直接在代码中被分配“”(或者这就是我的想法),就像:

String a = "";
String b = a;

assert "" == b ; // this is true 

不知何故(在阅读了代码之后,我有了一个线索)创建了两个不同的空字符串对象引用,我想知道如何

更多在jjnguys的答案:

字节!

编辑:结论

我已经找到了原因。

在jjnguy建议之后,我能够以不同的眼光看待代码。

有罪的方法:StringBuilder.toString()

分配并初始化一个新的 String 对象,以包含此对象当前表示的字符序列。

哎呀!...

    StringBuilder b = new StringBuilder("h");
    b.deleteCharAt( 0 );
    System.out.println( "" == b.toString() ); // prints false

谜团解开了。

该代码使用 StringBuilder 来处理不断增长的字符串。事实证明,在某个时候,有人这样做了:

 public void someAction( String string ) { 
      if( "" == string ) {
           return;
       }

       deleteBankAccount( string );
 }

和使用

 someAction( myBuilder.toString() ); // bug introduced. 

p.s. 我最近是否读了太多的 CodingHorror?或者为什么我觉得有必要在这里添加一些有趣的动物图片?


答案 1
String s = "";
String s2 = someUserInputVariale.toLowercase(); // where the user entered in ""

像这样的东西会导致评估为假。s == s2

许多代码门槛在不公开调用的情况下创建新的代码。Stringsnew String()


答案 2
"" == value // yields false

"".equals( value ) // yields true

任何时候变量的值尚未被暂留。如果在运行时计算该值,则会出现这种情况。请参阅 JLS 第 3.10.5 节字符串文本,了解说明以下内容的示例代码:value

因此,由编译单元组成的测试程序 (§7.3):

package testPackage;
class Test {
    public static void main(String[] args) {
        String hello = "Hello", lo = "lo";
        System.out.print((hello == "Hello") + " ");
        System.out.print((Other.hello == hello) + " ");
        System.out.print((other.Other.hello == hello) + " ");
        System.out.print((hello == ("Hel"+"lo")) + " ");
        System.out.print((hello == ("Hel"+lo)) + " ");
        System.out.println(hello == ("Hel"+lo).intern());
    }
}
class Other { static String hello = "Hello"; }

和编译单元:

package other;
public class Other { static String hello = "Hello"; }

产生输出:

true true true true false true

此示例说明了六点:

  • 同一包 (§7) 中同一类 (§8) 中的文本字符串表示对同一 String 对象 (§4.3.1) 的引用。
  • 同一包中不同类中的文本字符串表示对同一 String 对象的引用。
  • 不同包中不同类中的文本字符串同样表示对同一 String 对象的引用。
  • 由常量表达式 (§15.28) 计算的字符串在编译时计算,然后被视为文本。
  • 在运行时计算的字符串是新创建的,因此是不同的。
  • 显式插入计算字符串的结果与具有相同内容的任何预先存在的文本字符串的字符串相同。