This question already has answers here:
Comparing strings with == which are declared final in Java
(6 answers)
What is the difference between these two ways of initializing a String?
(3 answers)
Closed 7 years ago.
I am unable to recognize the difference in the following declarations of Strings in Java.
Suppose I am having two string
String str1="one";
String str2="two";
What is the difference between
String str3=new String(str1+str2);
and
String str3=str1+str2;
In both the above declarations, the content of str3 will be onetwo.
Suppose I create a new string
String str4="onetwo";
Then in none of the above declarations,
if(str4==str3) {
System.out.println("This is not executed");
}
Why are str3 and str4 not referring to the same object?
str1 + str2 for non-compilation-constant strings will be compiled into
new StringBuilder(str1).append(str2).toString(). This result will not be put, or taken from string pool (where interned strings go).
It is different story in case of "foo"+"bar" where compiler knows which values he works with, so he can concatenate this string once to avoid it at runtime. Such string literal will also be interned.
So String str3 = str1+str2; is same as
String str3 = new StringBuilder(str1).append(str2).toString();
and String str3 = new String(str1+str2); is same as
String str3 = new String(new StringBuilder(str1).append(str2).toString());
Again, strings produced as result of method (like substring, replace, toString) are not interned.
This means you are comparing two different instances (which store same characters) and that is why == returns false.
Java does not have memory of "how this variable got the value", therefore it really does not matter which method you use, if the result is same.
About comparing, if you compare strings with ==, you are comparing address of objects in memory, because String is not primitive data type, not values. You have to use if(str4.equals(str3))
Because Strings in Java are immutable the compiler will optimize and reuse String literals. Thus
String s1 = "one";
String s2 = "one";
s1 == s2; //true because the compiler will reuse the same String (with the same memory address) for the same string literal
s1 == "o" + "ne"; //true because "Strings computed by constant expressions are computed at compile time and then treated as if they were literals"
s3 = "o";
s1 == s3 + "ne"; //false because the second string is created a run time and is therefore newly created
for a reference see http://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.5
Strings are kind of tricky, because there is some effort to share their representation. Plus they're immutable.
The short answer is: unless you're really working in a low level, you should never compare strings using "==".
Even if it works for you, it will be a nightmare for your teammates to maintain.
For a longer answer and a bit of amusement, try the following:
String s1= "a" + "b";
String s2= "a" + "b";
String s3=new String("a"+"b");
System.out.println(s1==s2);
System.out.println(s3==s2);
You'll notice that s1==s2 due to the compiler's effort to share.
However s2 != s3 because you've explicitly asked for a new string.
You're not likely to do anything very smart with it, because it's immutable.
Related
I have read many artiles regarding string interning.
If I create a String object
Method 1
String str= new String("test")
2 Objects are created one in heap and other in string pool.
Method 2 if method 1 is not executed
String str= new String("test").intern()
it will create a copy of string frpoom heap to string pool .How many objects will be created.I guess 3.One will be in heap ,other in pool and one "test" literal.
Which one will be eligible for GC in both cases.I have seen artilces that say 2 are getting created but i am unable to understand why?
Method 3
String s= new String("test")
String s1=s.intern()
It does the same thing except the s point to heap object and s1 to pool object and none of them are eligible for Gc.
Is my understanding correct???I am confused a lot on this concept.
If I create a String object
String str= new String("test")
Objects are created one in heap and other in string pool.
A String consists of two objects, the String and the char[] In some version of Java it could be a byte[] Or in fact a char[] which is later replaced by a byte[]. This means that 4, perhaps 5 objects could be created, unless the String for the string literal already exists, in which cases it is 2 for Java 7 update 4+, before that the char[] would be shared so it could be three objects or only 1.
String str= new String("test").intern()
This is exactly the same except, if this is called enough the new String could be allocated on the stack and you might find that only the char[]` is created and this cannot be placed on the stack, at the moment. In future this might be optimised away also.
Which one will be eligible for GC in both cases.I have seen artilces that say 2 are getting created but i am unable to understand why?
The answer is anywhere from 1 to 4 depending on the situation. All of there eligible for collection unless they are being strongly referenced somewhere.
String intern() method:
The most common methods for String comparison are the equals() and equalsIgnoreCase() methods. However, these methods may need large amount of memory for large sequence of characters. The Java String intern() method helps us to improve the performance of the comparison between two Strings.
The intern() method, when applied to a String object, returns a reference to this object (from the hash set of Strings that Java makes), that has the same contents as the original object. Thus, if a code uses the intern() method for several String objects, then our program will use significantly less memory , because it will reuse the references of the objects in the comparison between these Strings.
Keep in mind, that Java automatically interns String literals. This means that the intern() method is to be used on Strings that are constructed with new String().
Example:
JavaStringIntern.java
package com.javacodegeeks.javabasics.string;
public class JavaStringIntern {
public static void main(String[] args) {
String str1 = "JavaCodeGeeks";
String str2 = "JavaCodeGeeks";
String str3 = "JavaCodeGeeks".intern();
String str4 = new String("JavaCodeGeeks");
String str5 = new String("JavaCodeGeeks").intern();
System.out.println("Are str1 and str2 the same: " + (str1 == str2));
System.out.println("Are str1 and str3 the same: " + (str1 == str3));
System.out.println("Are str1 and str4 the same: " + (str1 == str4)); //this should be "false" because str4 is not interned
System.out.println("Are str1 and str4.intern() the same: " + (str1 == str4.intern())); //this should be "true" now
System.out.println("Are str1 and str5 the same: " + (str1 == str5));
}
}
Output:
Are str1 and str2 the same: true
Are str1 and str3 the same: true
Are str1 and str4 the same: false
Are str1 and str4.intern() the same: true
Are str1 and str5 the same: true
Points to note is
Interning is automatic for String literals, the intern() method is to be used on Strings constructed with new String()
The Strings (more specifically, string objects) will be garbage collected if they ever become unreachable, like any other java objects.
String literals typically are not candidates for garbage collection. There will be a implicit reference from the Object to that literal.
Reason for point#3 is If a literal is being used inside a method to build a String is reachable for as long as the method could be executed.
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Java comparison with == of two strings is false? [duplicate]
(12 answers)
Closed 9 years ago.
Why is it that comparison of two strings having identical contents (s1==s2) returns true but (s3==s4) returns false if we initiate s1 and s2 with "=" but s3 and s4 with String constructor? #JAVA
Like
String s1="s";
String s2="s";
String s3= new String("s");
String s4= new String("s");
String s1 is a REFERENCE not an OBJECT. This means when you compare s1 == s2 you are comparing the references, not the contents of what those references point.
When you have two String literals which are the same, they are cached and the same object is used. This is done to save space. This means two string literals which have the same contents point to the same object.
When you create two new objects, they have different references so they are not equal, even if s3.equals(s4) is true.
I suggest you look at the String.intern() method which details how Strings are pooled.
So these are all true.
s1 == s2;
s1 == s3.intern();
s3.intern() == s4.intern();
s1 == s1.intern();
s1 == s1.intern().intern().intern();
s3 != s3.intern();
In hindsight, I think Java should have had a === for comparing references and == for comparing contents i.e. calling equals as this is a common source of confusion for developers who don't understand the difference between references and objects in Java.
This question already has answers here:
String comparison and String interning in Java
(3 answers)
How do I compare strings in Java?
(23 answers)
String.equals versus == [duplicate]
(20 answers)
Closed 10 years ago.
I'm new to this site and didn't realize there were other questions that answered what I'm asking. I've figured it out and I will delete this post as soon as it lets me. Thank you.
I just started learning java again and I have a quick question.
Usually, using == to compare strings would not work and you would have to use .equals instead.
But now while coding, I found they are doing the same thing when they are not supposed too and I'm trying to figure out why.
Here's the code.
String s = "Hello";
String x = "Hello";
if (x == s){
System.out.println("It is working!");
}//end if
else {
System.out.println("It is not working");
}//end else
if (x.equals(s)){
System.out.println("Match");
}//end if
else {
System.out.println("No match");
}//end else
Basically you're seeing the result of string interning. From section 15.28 of the JLS:
Compile-time constant expressions of type String are always "interned" so as to share unique instances, using the method String.intern.
So your two variable values actually refer to the same strings. If you use:
String s = new String("Hello");
String x = new String("Hello");
... then you'll see the behaviour you expect.
Reason is that your vars x and s have the same reference hence == behaves same as .equals.
When Java compiler optimizes your string values (literals), it determines that both x and s have same value and hence you need only one String object. As result, both x and s point to the same String object and some little memory is saved. It's safe operation since String is an immutable object in Java.
well, In this particular case there is only one string object created and cached in the string constant pool and both of the reference variables refer to the same string object which is stored in the string constant pool . thus you == test passes
String s = "Hello"; Line 1
String x = "Hello"; Line 2
When line 1 is executed one string object (Hello) is created and cached in String Constant pool .
**String Constant Pool:** {s--->"Hello"}
when line 2 is executed, it first checks if there is any object with the same value in string constant pool, if there exists one. it simply points the reference to the already created object in the pool.
**String Constant Pool:** {s,x--->"Hello"}
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
difference between string object and string literal
When initializing a String object there are at least two ways, like such:
String s = "some string";
String s = new String("some string");
What's the difference?
The Java language has special handling for strings; a string literal automatically becomes a String object.
So in the first case, you're initializing the reference s to that String object.
In the second case, you're creating a new String object, passing in a reference to the original String object as a constructor parameter. In other words, you're creating a copy. The reference s is then initialized to refer to that copy.
In first case you can take this string from pool if it exist there.
In second case you explicitly create new string object.
You can check this by these lines:
String s1 = "blahblah";
String s2 = "blahblah";
String s3 = new String("blahblah");
String s4 = s3.intern();
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s2 == s3);
System.out.println(s1 == s4);
Output:
true
false
false
true
String s = "some string"; assigns that value to s from string pool (perm.gen.space) (creates one if it does not exist)
String s = new String("some string"); creates a new string with value given in constructor, memory allocated in heap
The first method is recommended as it will help to reuse the literal from string pool
Semantically, the first one assigns "some string" to s, while the second one assigns a copy of "some string" to s (since "some string" is already a String). I see no practical reasons to do this in 99.9% of cases, thus I would say that in most contexts, the only difference between the two lines is that:
The second line is longer.
The second line might consume more memory than the first one.
As #Anish-Dasappan mentions, the second one will have it's value in heap, whereas the first one will be in the string pool - I'm not sure this has any interest for the programmer, but I might be missing a clever trick there.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
What is the purpose of the expression “new String(…)” in Java?
Hi,
1) What is difference in thers two statements:
String s1 = "abc";
and
String s1 = new String("abc")
2) as i am not using new in first statement, how string object will be created
Thanks
The first will use a fixed String that will be compiled in the code. The second variant uses the fixed String and creates a new String by copying the characters. This actually creates a new separate object in memory and is not necessary, because Strings are immutable. For more information, you can read this thread.
The main advantage of having internalized strings is that the performance is better (e.g. through caching etc.).
As a programmer there is no real upside to creating a new String, unless you come by the following example:
String sentence = "Lorem ipsum dolor sit amet";
String word = sentence.substring(5);
Now the word has a reference to the sentence (substring does not copy the characters). This is efficient while the sentence is also used, but when this one is thrown away you use a lot more memory than needed. In that case a new String can be created:
word = new String(word);
In the first case, the compiler knows the value of the String s1. Thus, all strings with the same value will use the same memory locations:
String s1 = "abc";
String s2 = "abc";
Although there are two String references (s1 and s2), there is only one "abc" sequence in memory. The new operator is not needed because the compiler does the job.
In the second case, the compiler doesn't perform the evaluation of the String value. Thus, the sentence will generate a new instance of String, at runtime:
String s1 = "abc";
String s2 = new String("abc");
The constant "abc" in line 1 references the same memory as the constant "abc" in line 2. But the net effect of line 2 is the creation of a new String instance.