了解Java中字符串比较的工作原理

了解Java中字符串比较的工作原理,java,string,string-comparison,Java,String,String Comparison,可能重复: 我是Java新手,在理解字符串比较方面有困难。有人能解释一下以下场景之间的区别吗 场景1: String a = "abc"; String b = "abc"; String a = new String("abc"); String b = new String("abc"); 当我运行if(a==b)时,它返回true 场景2: String a = "abc"; String b = "abc"; String a = new String("

可能重复:

我是Java新手,在理解字符串比较方面有困难。有人能解释一下以下场景之间的区别吗

场景1:

String a = "abc";    
String b = "abc";
String a = new String("abc");    
String b = new String("abc");
当我运行
if(a==b)
时,它返回true

场景2:

String a = "abc";    
String b = "abc";
String a = new String("abc");    
String b = new String("abc");
如果(a==b)运行
,则返回false


区别是什么?

=
操作符比较内存中两个对象的引用。如果它们指向同一位置,则返回true。
String
对象在java中是,因此,当您在场景1中创建字符串时,它不会创建新字符串。它只是将第二个字符串指向第一个字符串的内存位置

但是,
.equals()
方法比较字符串的内容。当字符串具有相同的值时,此方法返回true


因此,通常建议使用
equals()
方法,而不是
=

由于编译器优化,场景1返回true

通常,您应该使用
equals()
而不是
=
来比较字符串。

这是因为Java字符串常量内存池。相同值的文本只存储一次

String a = "abc";
String b = "abc";
// Now there is 1 string ("abc") and 2 references pointing to it.

String a = new String("abc");
String b = new String("abc");
// Now you have 2 string instances and 2 references.

在Java中,您需要像这样使用if(str.equals(str2))
,它比较字符串的实际值而不是引用值。

Case1:

 String a = "abc";
    String b = "abc";
    if(a == b)
String a = new String("abc");
String b = new String("abc");
and run if(a == b) then it returns false.
在这种情况下,
abc
缓存在字符串常量池中,因此不会创建新字符串
String b=“abc”
b
只是指由a创建的字符串,当
a
b
都指向内存中的同一对象时,它返回true

案例2:

 String a = "abc";
    String b = "abc";
    if(a == b)
String a = new String("abc");
String b = new String("abc");
and run if(a == b) then it returns false.

这里创建了两个字符串,
=
操作符只检查两个引用是否指向同一个引用,在本例中它不会这样做,因此它返回false

原因是字符串文本
“abc”
将被转换为其所有引用的全局字符串实例,它将是相同的字符串实例,因此您可以确保
“abc”==“abc”
。编译器可以这样做,因为字符串实例是不可变的。但是,如果显式分配字符串,则它们将是两个不同的实例,并且它们也将不同于编译器隐式创建的字符串实例,即
newstring(“abc”)!=新字符串(“abc”)
“abc”!=新字符串(“abc”)

了解编译器正在做什么的另一个好例子是查看以下代码:

"abc".contains("a");
您可以看到,文本的行为类似于字符串类型的实例。您可以利用此漏洞来最小化编程错误,例如

// this is OK and the condition will evaluate to false
String myStringValue = null;
if ("abc".equals(myStringValue)) { // false
鉴于此代码导致NPE:

// this will produce a NPE    
String myStringValue = null;
if (myStringValue.equals("abc")) { // NPE 

创建字符串的两种方法是 1) 字符串s=“hello”;字符串文本的数量=1,即“hello”-堆上字符串对象的数量=0

2) String s=新字符串(“hello”);-字符串文字数=1,字符串对象数=1

Java维护一个“文本”字符串池,对象将留在堆上

字符串池的优点:1)减少内存使用*(PermGenSpace问题)2)更快的比较,即==比较3)更快的查找 缺点:1)维护池的开销


如何共享字符串对象?对字符串使用Intern()将其添加到池中。实习的缺点:1)您可能会忘记实习一些字符串,并通过==对它们进行比较,从而导致意外的结果。

我是否要对每个不包含实习参考的答案进行否决投票?我可能:)阅读了关于字符串的内容。intern()case2可能会返回true,这取决于@owlstead接受的优化(interning),但无论如何,这里的情况不是这样的:)是的,问题是什么?您可能有一个实例,它取决于运行时,甚至可能取决于编译器。没有提到实习,因为这是在Q/A:。我在向下投票前发出了警告。大多数时候,当我执行字符串比较时,我将程序编码为两个字符串实例。如果我的方法允许一个
null
值作为参数,我甚至可以单独检查
null
。在这种情况下,我希望应用程序抛出一个NPE,而不是在一个(可能)未定义的状态下愉快地运行。一个问题,许多解决方案,选择你的颜色,并对它感到满意。我使用我解释过的方法优雅地最小化编程错误。每次遇到这个特殊问题时,我都会选择一种颜色。不过,每次可能遇到异常时,只是在表下拖拽异常并不是一个解决方案,我至少希望读者注意到这一点,因此有这样的评论。如果你将其称为拖拽异常,那只会暴露出你对该语言的无知,你的编码风格更容易出错,不必要地过于保守。这是你的坏作风,但我不是来打扰你的。