问题
I'm trying to understand how the String pool works and what are the rules for a string to be equal to another String.
For example this snippet :
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
}
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 ?
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 ?
PS: I use string1.equals(string2) everywhere no matter what. I just want a deeper understanding of the underlying mechanism.
回答1:
- 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 ?
No, not correct. There is already a string "lol" in the string pool, so it's not going to create a duplicate. However, you are not doing anything with the return value of the call to intern()
so s3
is still referring to the String
object that is not in the pool.
Try s3 = s3.intern();
instead of just 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 ?
The whole point of the String pool is to avoid duplicate strings in memory, so there will not be any duplicates in the String pool.
回答2:
Your s3.intern();
should be s3 = s3.intern();
to get the correct behaviour.
回答3:
basically we can create Sting by two ways
String str="some data" (not bound to any object like primitive data type)
String strTwo=new String("some String"); (here strTwo object contains value)
As the name suggests, String Pool is a pool of Strings stored in Java Heap
Memory. We know that String is special class in java and we can create String object using new operator as well as providing values in double quotes.
String Pool is possible only because String is immutable in Java and it’s implementation of String interning concept. String pool is also example of Flyweight design pattern.
String pool helps in saving a lot of space for Java Runtime although it takes more time to create the String.
When we use double quotes to create a String, it first looks for String with same value in the String pool, if found it just returns the reference else it creates a new String in the pool and then returns the reference.
However using new operator, we force String class to create a new String object and then we can use intern() method to put it into the pool or refer to other String object from pool having same value.
as
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));
}
and output
[![s1 == s2 :true
s1 == s3 :false
回答4:
There is difference when comparing string literals which are always taken from the pool (case s1 and s2) with comparing string literal or string created on runtime with constructor to another string created with new.
String literal is guaranteed to be taken from string pool when exact same literal already exists. String object still internally uses string from the pool, but as an object has different reference.
String#intern();
returns reference to string from pool, that is internally used.
Code snippet to show this behavior:
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));
And the output:
literalOne == literalTwo ? true
stringOne == stringTwo ? false
Internally stringOne == stringTwo ? true
Internally stringOne == literalOne ? true
回答5:
== compares references, so when you try s1 == s3 you are checking to see if these two references point to the same object which is not true since you have created s3 as a new object(new String("lol")).So now the string pool has two different objects that happen to have the same string value("lol") and in your code you have s1,s2,s4 pointing to one and s3 pointing to the other.
In order for you to compare the values of each object that is been referenced you must use equals() method.
来源:https://stackoverflow.com/questions/37694995/rules-for-string-a-string-b