字符串 a == 字符串 b 的规则
Rules for String a == String b
我正在尝试了解字符串池的工作原理以及一个字符串与另一个字符串相等的规则是什么。
例如这个片段:
public static void main(String[] hi){
String s1 = "lol";
String s2 = "lol";
String s3 = new String("lol");
System.out.println( s1 == s2 );// true
System.out.println( s2 == s3); // false
s3.intern(); //line 1
System.out.println( s1 == s3); // false
testString(s1);
}
private static void testString(String s1){
String s4 = "lol";
System.out.println( s1 == s4); // true
}
在//第 1 行:字符串被添加到字符串池中。因为它不等于 s1,所以我假设字符串池中有重复项。正确 ?
池中有重复项的规则是什么?换句话说,什么时候 someString == someString
return false 即使两个字符串具有相同的字符序列?
PS:无论如何,我到处都使用string1.equals(string2)。我只是想更深入地了解底层机制。
将始终从池中获取的字符串文字(案例 s1 和 s2)与将运行时使用构造函数创建的字符串文字或字符串与使用 new 创建的另一个字符串进行比较时存在差异。
当完全相同的文字已经存在时,保证从字符串池中获取字符串文字。字符串对象仍然在内部使用池中的字符串,但作为对象具有不同的引用。
String#intern();
returns 引用池中的字符串,供内部使用。
显示此行为的代码片段:
String literalOne = "abc";
String literalTwo = "abc";
String stringOne = new String("abc");
String stringTwo = new String("abc");
System.out.println("literalOne == literalTwo ? " + (literalOne == literalTwo));
System.out.println("stringOne == stringTwo ? " + (stringOne == stringTwo));
System.out.println("Internally stringOne == stringTwo ? " + (stringOne.intern() == stringTwo.intern()));
System.out.println("Internally stringOne == literalOne ? " + (stringOne.intern() == literalOne));
并且输出:
literalOne == literalTwo ? true
stringOne == stringTwo ? false
Internally stringOne == stringTwo ? true
Internally stringOne == literalOne ? true
== 比较引用,所以当您尝试 s1 == s3 时,您正在检查这两个引用是否指向同一个对象,这是不正确的,因为您已将 s3 创建为新对象(new String("lol")). 所以现在字符串池有两个不同的对象,它们恰好具有相同的字符串值 ("lol") 并且在你的代码中你有 s1,s2,s4 指向一个和 s3 指向其他.
为了比较被引用的每个对象的值,您必须使用 equals() 方法。
您的 s3.intern();
应该是 s3 = s3.intern();
以获得正确的行为。
基本上我们可以通过两种方式创建Sting
String str="some data" (not bound to any object like primitive data type)
String strTwo=new String("some String"); (here strTwo object contains value)
顾名思义,字符串池是存储在Java Heap
内存中的字符串池。我们知道 String 在 java 中是特殊的 class 并且我们可以使用 new 运算符创建 String 对象并在双引号中提供值。
String Pool 之所以可行,只是因为 String 在 Java 中是不可变的,并且它是 String interning 概念的实现。字符串池也是享元设计模式的一个例子。
字符串池有助于为 Java 运行时节省大量 space,尽管创建字符串需要更多时间。
当我们使用双引号创建一个字符串时,它首先在字符串池中查找具有相同值的字符串,如果找到它只是 returns 引用,否则它会在池中创建一个新的字符串,然后returns参考。
但是使用new运算符,我们强制Stringclass创建一个新的String对象,然后我们可以使用intern()方法将其放入池中或引用其他String对象来自具有相同值的池。
作为
public void method(){
String s1 = "Cat";
String s2 = "Cat";
String s3 = new String("Cat");
System.out.println("s1 == s2 :"+(s1==s2));
System.out.println("s1 == s3 :"+(s1==s3));
}
并输出
[![s1 == s2 :true
s1 == s3 :false
- At //line 1: the string is added to the string pool. Since it's not equal to s1 I assume there is a duplicate in the string pool. Correct ?
不,不正确。字符串池中已经有一个字符串 "lol",因此它不会创建重复项。但是,您没有对 intern()
调用的 return 值执行任何操作,因此 s3
仍然引用不在池中的 String
对象。
试试 s3 = s3.intern();
而不是 s3.intern();
- What is the rule for having a duplicate in the pool ? In other words when does someString == someString return false even though both string have the same char sequence ?
String pool的全部意义在于避免内存中出现重复的字符串,所以String pool中不会有任何重复的。
我正在尝试了解字符串池的工作原理以及一个字符串与另一个字符串相等的规则是什么。
例如这个片段:
public static void main(String[] hi){
String s1 = "lol";
String s2 = "lol";
String s3 = new String("lol");
System.out.println( s1 == s2 );// true
System.out.println( s2 == s3); // false
s3.intern(); //line 1
System.out.println( s1 == s3); // false
testString(s1);
}
private static void testString(String s1){
String s4 = "lol";
System.out.println( s1 == s4); // true
}
在//第 1 行:字符串被添加到字符串池中。因为它不等于 s1,所以我假设字符串池中有重复项。正确 ?
池中有重复项的规则是什么?换句话说,什么时候
someString == someString
return false 即使两个字符串具有相同的字符序列?
PS:无论如何,我到处都使用string1.equals(string2)。我只是想更深入地了解底层机制。
将始终从池中获取的字符串文字(案例 s1 和 s2)与将运行时使用构造函数创建的字符串文字或字符串与使用 new 创建的另一个字符串进行比较时存在差异。
当完全相同的文字已经存在时,保证从字符串池中获取字符串文字。字符串对象仍然在内部使用池中的字符串,但作为对象具有不同的引用。
String#intern();
returns 引用池中的字符串,供内部使用。
显示此行为的代码片段:
String literalOne = "abc";
String literalTwo = "abc";
String stringOne = new String("abc");
String stringTwo = new String("abc");
System.out.println("literalOne == literalTwo ? " + (literalOne == literalTwo));
System.out.println("stringOne == stringTwo ? " + (stringOne == stringTwo));
System.out.println("Internally stringOne == stringTwo ? " + (stringOne.intern() == stringTwo.intern()));
System.out.println("Internally stringOne == literalOne ? " + (stringOne.intern() == literalOne));
并且输出:
literalOne == literalTwo ? true
stringOne == stringTwo ? false
Internally stringOne == stringTwo ? true
Internally stringOne == literalOne ? true
== 比较引用,所以当您尝试 s1 == s3 时,您正在检查这两个引用是否指向同一个对象,这是不正确的,因为您已将 s3 创建为新对象(new String("lol")). 所以现在字符串池有两个不同的对象,它们恰好具有相同的字符串值 ("lol") 并且在你的代码中你有 s1,s2,s4 指向一个和 s3 指向其他.
为了比较被引用的每个对象的值,您必须使用 equals() 方法。
您的 s3.intern();
应该是 s3 = s3.intern();
以获得正确的行为。
String str="some data" (not bound to any object like primitive data type)
String strTwo=new String("some String"); (here strTwo object contains value)
顾名思义,字符串池是存储在Java Heap
内存中的字符串池。我们知道 String 在 java 中是特殊的 class 并且我们可以使用 new 运算符创建 String 对象并在双引号中提供值。
String Pool 之所以可行,只是因为 String 在 Java 中是不可变的,并且它是 String interning 概念的实现。字符串池也是享元设计模式的一个例子。
字符串池有助于为 Java 运行时节省大量 space,尽管创建字符串需要更多时间。
当我们使用双引号创建一个字符串时,它首先在字符串池中查找具有相同值的字符串,如果找到它只是 returns 引用,否则它会在池中创建一个新的字符串,然后returns参考。
但是使用new运算符,我们强制Stringclass创建一个新的String对象,然后我们可以使用intern()方法将其放入池中或引用其他String对象来自具有相同值的池。
作为
public void method(){
String s1 = "Cat";
String s2 = "Cat";
String s3 = new String("Cat");
System.out.println("s1 == s2 :"+(s1==s2));
System.out.println("s1 == s3 :"+(s1==s3));
}
并输出
[![s1 == s2 :true
s1 == s3 :false
- At //line 1: the string is added to the string pool. Since it's not equal to s1 I assume there is a duplicate in the string pool. Correct ?
不,不正确。字符串池中已经有一个字符串 "lol",因此它不会创建重复项。但是,您没有对 intern()
调用的 return 值执行任何操作,因此 s3
仍然引用不在池中的 String
对象。
试试 s3 = s3.intern();
而不是 s3.intern();
- What is the rule for having a duplicate in the pool ? In other words when does someString == someString return false even though both string have the same char sequence ?
String pool的全部意义在于避免内存中出现重复的字符串,所以String pool中不会有任何重复的。