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.
Related
I have two strings and I am trying to copy one into another. How I can copy character by character a string into another in Java?.
Strings are immutable objects in Java, which means that after they are instantiated, they will not change internal state. Instead, if you want to modify a String, you will always get a new String.
Now, to your question. If you want to copy a String chararcter by character this is highly inefficient, since you would create a new String object each time you copy a character. Luckily, there are plenty of other options.
String a = "a";
String b = "b";
String c = a + b; // "ab"
String d = a.concat(b); // "ab"
If you simply want to copy a String, you can do the following:
String e = a; "a"
Why does that work? As stated earlier, Strings a immutable, thus a new String with the same content is created. You can think of it as String e = new String(a), which is slightly less performant (and therefore an antipattern), but also works.
I was studying Kathy Sierra Java book. I came across one question something like this:
public class A {
public static void main(String args[]){
String s1 = "a";
String s2 = s1;
//s1=s1+"d";
System.out.println(s1==s2);
}
}
output: true
Two points I didn't understand here are:
when I uncomment s1 = s1 + "d" output changes to false. Same thing happens if I replace String with wrapper Integer or int.
Again, when I change my code to use StringBuffer like this:
StringBuffer sb = new StringBuffer("a");
StringBuffer sb2 = sb;
//sb.append("c");
System.out.println(sb == sb2);
now the output doesn't changes i.e. it remains true even if I uncomment the sb.appendstatement.
I can't understand this strange behavior. Can some one explain me.
s2 is a reference to s1 in the first case. In the second case, + is translated to s1.concat("d") which creates a new string, so the references s1 and s2 point to different string objects.
In the case of StringBuffer, the reference never changes. append changes the internal structure of the buffer, not the reference to it.
Immutable scenario
The String class and wrapper classes like Integer and Double are all immutable. This means that when you do something like:
1. String s1 = "a";
2. s2 = s1;
3. s1 = s1 + "b";
4. System.out.println(s1 == s2); // prints false
Notice what really happens under the covers (very simplified, and using bogus memory addresses):
(line 1) Create a string "a" at memory address 0x000001.
(line 1) Set the value of s1 to 0x000001 so that it effectively points to string "a".
(line 2) Copy the value of s1 and set it to s2. So now both s1 and s2 have the same value of 0x000001, and so both point to string "a".
(line 3) Find what s1 is pointing to (string "a"), and use that to create a new and distinct string of "ab" that will live at a different memory address of 0x000002. (Note that string "a" remains unchanged at memory address 0x000001).
(line 3) Now assign value 0x000002 to variable s1 so that it now effectively points to this new string "ab".
(line 4) Compare the values of s1 and s2, which are now at 0x000002 and 0x000001 respectively. Clearly, they don't have the same values (memory addresses) so the result is false.
(line 4) Print false to the console.
So you see, when changing the "a" string to a "ab" string, you were not modifying the "a" string. Rather, you were creating a 2nd distinct string with the new value of "ab", and then changing a reference variable to point to this newly created string.
The exact same pattern occurs when coding with the other classes like Integer or Double, which are immutable as well. You have to understand that when you use operators like + or - on instances of these classes, you are not modifying the instance in any way. Rather, you are creating a whole new object, and getting a new reference to that new object's memory address that you can then assign to a reference variable.
Mutable scenario
This is in complete contrast to mutable classes like StringBuffer or StringBuilder, and others like the unfortunate java.util.Date. (BTW, it's best you get in the habit of using StringBuilder instead of StringBuffer, unless you are using it on purpose for a multi-threaded requirement)
With mutable classes, the exposed methods of these classes do change (or mutate) the internal state of the object, instead of creating a whole new object. As a result, if you have multiple variables pointing to the same mutable object, if one of those variables is used to access the object and make changes to it, accessing that same object from any of the other variables will see the changes as well.
So if we take this code, for instance (again, please use StringBuilder instead, the net result will be the same):
1. StringBuffer sb = new StringBuffer("a");
2. StringBuffer sb2 = sb;
3. sb.append("b");
4. System.out.println(sb == sb2); // prints true
Notice how different this is handled internally (again, very simplified, even omitting some details to keep it simple and understandable):
(line 1) Create a new StringBuffer instance at memory address 0x000001 with an internal state of "a".
(line 1) Set the value of sb to 0x000001 so that it effectively points to the StringBuffer instance, which itself contains "a" as part of its state.
(line 2) Copy the value of sb and set it to sb2. So now both sb and sb2 have the same value of 0x000001, and so both point to the same StringBuffer instance.
(line 3) Find what sb is pointing to (the StringBuffer instance), and call the .append() method on it to ask it to mutate its state from "a" to "ab". (Very important!!! Unlike the immutable version, the memory address of sb does NOT change. So both sb and sb2 are still pointing to the same StringBuffer instance.
(line 4) Compare the values of sb and sb2, which are both still at 0x000001. This time, they both have the same value, so the result is true.
(line 4) Print true to the console.
Bonus consideration: == vs. equals()
Once you understand the above, then you now have the required knowledge to better understand this peculiar scenario:
1. String s1 = "abc";
2. String s2 = new String(s1);
3. System.out.println(s1 == s2); // prints false?!?
4. System.out.println(s1.equals(s2)); // prints true
Surprisingly, line 3 returns false (?!?). However, once we understand what the == operator is comparing, combined with a better understanding of immutable classes like String, then it's actually not that hard to understand, and it teaches us a valuable lesson.
So if we do the exercise again of examining what is really happening, we find the following:
(line 1) Create string "abc" at memory address 0x000001.
(line 1) Set the value of s1 to 0x000001 so that it effectively points to string "abc".
(line 2) Create a new string "abc" at memory address 0x000002. (Note that we now have 2 strings "abc". One at memory address 0x000001, and the other one at 0x000002).
(line 2) Set the value of s2 to 0x000002 so that it effectively points to the 2nd string "abc".
(line 3) Compare the values of s1 and s2, which are now at 0x000001 and 0x000002 respectively. Clearly, they don't have the same values (memory addresses) so the result is false. (Even though they are both pointing to strings that are the same logically speaking, in memory, they are still 2 distinct strings!)
(line 3) Print false to the console.
(line 4) Call .equals() on the string pointed to by variable s1 (address 0x000001). And as a parameter, pass a reference to the string pointed to by variable s2 (address 0x000002). The equals method compares the values of both strings, and determines that they are logically equal, so it returns true.
(line 4) Print true to the console.
Hopefully, the above now makes sense to you.
And the lesson?
== is not the same as equals().
== will blindly check to see if the variables' values are the same. In the case of reference variables, the values are memory address locations. So, even if 2 variables point to logically equivalent objects, if they are different objects in memory, it will return false.
equals() is meant to check for logical equality. What that means exactly depends on the specific implementation of the equals() method that you invoke. But in general, this is the one that returns the result we expect intuitively, and is the one you want to use when comparing strings to avoid nasty unexpected surprises.
If you need more information, I recommend you do further searches on the topic of immutable vs mutable classes. And also on the topic of value vs. reference variables.
I hope this helps you.
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.
I have been given the following condition?
String A="a";
String B="b";
String c="a"+"b";
My question is is the String c created newly or is assigned from the string pool the value "a" and "b" and total how many strings are formed according to above question?
Yes c is created newly. Strings in Java are effectively immutable (i.e. once created, they never change). One of the consequences of this is that, whenever you do a manipulation that changes a string, you get back a new, different object.
So in your example, 3 strings are created.
Take these two String objects:
String a = "a";
String b = "b";
String c = "a" + "b";
String d = "ab";
The compiler creates and pools three String objects. A line by line explanation follows.
Line 1: One String object is pooled for "a"
Line 2: One String object is pooled for "b"
Line 3: "a" + "b" is computer at compile time and treated as a literal. Therefore, one String object is pooled for "ab"
Line 4: "ab" is already in the pool
Following the same guidelines, your example produces 3 String objects.
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.