how java string immutable? [duplicate] - java

This question already has answers here:
String is immutable. What exactly is the meaning? [duplicate]
(19 answers)
Closed 8 years ago.
I have a string in method in java class as below
public void show(){
String s1;
s1 = "abc";
s1 = "def";
System.out.println(s1);
}
Here the output is def, but as String is immutable so I don't understand how string s1 is immutable here as I can change the String s1 content from abc to def.
Could you please make me understand this?

You did not change the string; you changed the variable s1 so that it refers to a different string. The original string "abc" still exists and has not been modified (and cannot be modified, because strings are immutable).
Try this:
public void show() {
String s1 = "abc";
String s2 = s1;
System.out.println("s1 is same object is s2? = " + (s1 == s2));
s1 = "def";
System.out.println("s1 = " + s1);
System.out.println("s2 = " + s2);
}
Notice that setting s1 to refer to a new string did not affect the original string, so s2 still refers to it.

By mutable, you mean that you have the same object and you are able to modify its state (like say your class having a Date object). So immutable is exactly the opposite. Consider Date class and i define it like:
Date date = new Date();//print it and you will get today's date
date.setTime(date.getTime() - 10days in millis);//print and see you changed your date by bask 10 days which you changed internal state (field) of Date
Now in your example, you are reassigning a new String to your s1 String i.e. changing the reference to point from one string to the other. You are not changing the internal character array i.e. field of your String object.

String is immutable means that you cannot change the object itself, but you can change the reference to the object. When you called
s1 = "abc";
s1 = "def";
, you are actually changing the reference of s1 to a new object created by the String literal "def".
S1 is only the reference to the Object , it is not the actual object
Try this way
s1="abc";
s1.toUpperCase();
System.out.println(s1);
Output will be still
abc
Since s1.toUpperCase() instead of changing the contents of String s1 it creates a new Object with Upper Case Contents but since we haven't catch the returning variable that is why output is still same
Now try using
s1="abc";
s1=s1.toUpperCase();
System.out.println(s1);
Now output
ABC

If you try to create string object. The memory will be created on heap as well as in the string pool. For example: String str=new String("hello");
For the variable str memory will be created on heap with value "hello" as well as string "hello" will be created in the string pool. str is the reference variable which will refer to the "hello" in the string pool.
Now if you try to create
String s1="hello";
Here s1 is the reference variable.String pool already has the value "hello". So s1 will refer to that "hello".
Same like this concept. s1 is the reference variable. It first refers the "abc" at String pool. then it refers to "def" at string pool. You didn't make any change on the "abc" or "def" at the string pool because they are immutable. If you want to create mutable string go for StringBuffer and StringBuilder.

Related

Count Distinct String Object Instances

How many distinct String object instances are created in the following code segment?
String s1 = new String("hello");
String s2 = "GoodBye";
String s3 = s1;
Not sure about all my reasoning here.
By using the keyword new that creates an instance from the String class, I am guessing that has to be an object. However, I am confused, is String after the new now considered a method because it has ( ) and then it is calling a String literal "hello" in it?
String s2 = "Goodbye";
I think this is a String literal, and since Strings are actually objects even the String literal is considered object. Not 100% sure if that is true.
String s3 = s1; Just refers back to s1. Therefore, it is not distinct.
So my answer is 2 distinct objects.
Please explain if I am a right or wrong.
The correct answer is 3.
String s1 = new String("hello");
String s2 = "GoodBye";
String s3 = s1;
The compiler will put both literals "hello" and "GoodBye" into a "constant pool" during compilation time, which then will be loaded by the classloader. So the JVM automatically interns all String literals used by this class, when it loads that class. More about this: When are Java Strings interned?. The String constant pool is then managed during runtime.
During runtime the JVM will create the third String object when it reaches the line String s1 = new String("hello").
So you would and up with three distinct String objects, where two of them contain the same word "hello". So s1.equals("hello") would be true, but s1 == "hello" would be false, because s1 references to a different String on the heap, than the literal "hello".
The line String s3 = s1 just creates a variable s3 with a copied reference to the String object of s1. It doesn't create a new object.
Also mind that you can "manually" add Strings into the String constant pool by using the method String#intern. So s1.intern() == "hello" is true, because the String reference returned from s1.intern() is the reference to the literal "hello" which was already in the constant pool.
If you like to get another and maybe more detailed explanation with some drawings about objects and their location, you can check this article on javaranch.

if string objects are interned then why change in one does not affect other [duplicate]

This question already has answers here:
What is the difference between a variable, object, and reference? [duplicate]
(5 answers)
Closed 7 years ago.
if string objects are interned then why change in one does not affect other
public class EqualExample {
public static void main(String[] args) {
String str = new String("Hello");
String str1 = new String("Hello");
System.out.println(str == str1);
System.out.println(str1.equals(str));
}
}
Output of above programe would be
false
true
public class EqualExample {
public static void main(String[] args) {
String str = "Hello";
String str1 = "Hello";
System.out.println(str == str1);
System.out.println(str1.equals(str));
}
}
Output of above code is
true
true
this is because in string pool Heloo alredy exists so it intern the string and refer to same object then why if i change str1 to "heloo java" then why str still have value "heloo". because they refer to same objects so the value of str must be change
public class EqualExample {
public static void main(String[] args) {
String str = "Hello";
String str1 = "Hello";
System.out.println(str == str1);
System.out.println(str1.equals(str));
str1="Heloo java";
System.out.println(str+str1);
System.out.println(str == str1);
System.out.println(str1.equals(str));
}
}
output true
true
HelooHeloo java
false
false
str1 is not a String. It is a reference to a String object. By doing
str1 = "Heloo java";
you're not modifying the String object, you're simply making the reference point to another, different String object.
Before:
str --------> "Hello"
^
str1 -----------|
After:
str --------> "Hello"
str1 -------> "Heloo Java"
Changing the object would consist in doing something like
str1.setCharacters("Heloo Java");
but such a method doesn't exist, because Strings are immutable. Their characters thus can't be modified (except by using dirty reflection tricks).
You have two pointers pointing to the same address in memory. Changing one value means redirecting one pointer while the other one remains unchanged.
You can't change an existing String. String is immutable. When you say 'changing str1 to "heloo java"' you are in fact assigning a reference to a different immutable object.
String str = "Hello"
Means
if "Hello" exists in the pool,
then return "Hello" instance reference from pool
else
create an object "Hello". Keep the object in the pool, then return reference
But
String str = new String("Hello");
means
Always create "Hello" object, irrespective of whether it exists in the pool or not.
According to Java Docs, Strings are Immutable. That is: they don't change, or, once created: they never change (the state of the Object, not the reference variable.)
However, you can change the reference variable, creating a new String Object , in an existing reference variable. If there is no reference variable pointing to the "old" String Object, the "old" String Object is considered inaccessible by your program, and the Garbage Collector may clean it.
in practice, with comment explaining in the code:
public static void main(String[] args) {
String s1 = "Test 1";
String s2 = s1;
System.out.println("s1: "+s1+ " and s2: "+s2);
s2 = "String 2";
System.out.println("s1: "+s1+ " and s2: "+s2);
//Garbage Collector will not clean the "String 1" because we still have the s1 Reference Variable pointing.
}
OUTPUT:
s1: Test 1 and s2: Test 1
s1: Test 1 and s2: String 2
As you mentioned, to offer better performance, JVM don't create a new String object in the Heap if the new String created is "meaningfully equal" (pass in the String.equals method) to a existing one in the Heap. But you can force this creation by new String("test 1") in the reference variable.
This Immutable state of String is to guarantee the good work of your program. Imagine how dangerous could be if you have two references of String and one of then changes: the other will be changed too and Strange Things could happen.
Java Classes are Immutable too; like the Wrapper Classes: java.lang.Integer, java.lang.Double, ....
I have illustrated the Garbage Collector to you deeply understand the Reference Variable relation with the Object in the Heap.

what happens with new String("") in String Constant pool

if i create a string object as
String s=new String("Stackoverflow");
will String object created only in heap, or it also makes a copy in String constant pool.
Thanks in advance.
You only get a string into the constant pool if you call intern or use a string literal, as far as I'm aware.
Any time you call new String(...) you just get a regular new String object, regardless of which constructor overload you call.
In your case you're also ensuring that there is a string with contents "Stackoverflow" in the constant pool, by the fact that you're using the string literal at all - but that won't add another one if it's already there. So to split it up:
String x = "Stackoverflow"; // May or may not introduce a new string to the pool
String y = new String(x); // Just creates a regular object
Additionally, the result of a call to new String(...) will always be a different reference to all previous references - unlike the use of a string literal. For example:
String a = "Stackoverflow";
String b = "Stackoverflow";
String x = new String(a);
String y = new String(a);
System.out.println(a == b); // true due to constant pooling
System.out.println(x == y); // false; different objects
Finally, the exact timing of when a string is added to the constant pool has never been clear to me, nor has it mattered to me. I would guess it might be on class load (all the string constants used by that class, loaded immediately) but it could potentially be on a per-method basis. It's possible to find out for one particular implementation using intern(), but it's never been terribly important to me :)
In this case you are constructing an entirely new String object and that object won't be shared in the constant pool. Note though that in order to construct your new String() object you actually passed into it a String constant. That String constant is in the constants pool, however the string you created through new does not point to the same one, even though they have the same value.
If you did String s = "Stackoverflow" then s would contain a reference to the instance in the pool, also there are methods to let you add Strings to the pool after they have been created.
The new String is created in the heap, and NOT in the string pool.
If you want a newly create String to be in the string pool you need to intern() it; i.e.
String s = new String("Stackoverflow").intern();
... except of course that will return the string literal object that you started with!!
String s1 = "Stackoverflow";
String s2 = new String(s1);
String s3 = s2.intern();
System.out.println("s1 == s2 is " + (s1 == s2));
System.out.println("s2 == s3 is " + (s2 == s3));
System.out.println("s1 == s3 is " + (s1 == s3));
should print
s1 == s2 is false
s2 == s3 is false
s1 == s3 is true
And to be pedantic, the String in s is not the String that was created by the new String("StackOverflow") expression. What intern() does is to lookup the its target object in the string pool. If there is already a String in the pool that is equal(Object) to the object being looked up, that is what is returned as the result. In this case, we can guarantee that there will already be an object in the string pool; i.e. the String object that represents the value of the literal.
A regular java object will be created in the heap, and will have a reference s type of String. And, there will be String literal in String Constant Pool. Both are two different things.
My answer is YES!
Check the following code first:
String s0 = "Stackoverflow";
String s1 = new String("Stackoverflow");
String s2 = s1.intern();
System.out.println(s0 == s1);
System.out.println(s1 == s2 );
System.out.println(s0 == s2);
//OUTPUT:
false
false
true
s0 hold a reference in the string pool, while new String(String original) will always construct a new instance. intern() method of String will return a reference in the string pool with the same value.
Now go back to your question:
Will String object created only in heap, or it also makes a copy in String constant pool?
Since you already wrote a string constant "Stackoverflow" and pass it to your String constructor, so in my opinion, it has the same semantic as:
String s0 = "Stackoverflow";
String s1 = new String(s0);
which means there will be a copy in String constant pool when the code is evaluated.
But, if you construct the String object with following code:
String s = new String("StackoverflowSOMETHINGELSE".toCharArray(),0,13);
there won't be a copy of "Stackoverflow" in constant pool.

Diff bet new String("xyz") and "xyz" in Java [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
difference between string object and string literal
Hello,
Foremost, let’s come up with Java facts with String
Strings are immutable
My Question - If Strings are immutable then below statement should have compilation error!
String str = "xyz";
or
String str = new String("xyz");
str = "abc"; //COMPILATION ERROR
or
str = new String("abc"); //COMPILATION ERROR
What is the difference between below instantiation ?
String str = "xyz";
and
String str = new String("xyz");
Amit.
Strings are immutable means you can't do something like str[1] = 'x' i.e you cannot change the content of the string.
This will answer your second question.
Strings are immutable, so you cannot change the contents of a string.
In the following code:
String str = "xyz";
str = "abc";
you're not changing the contents of a String instance, but rather assigning a new String instance to the variable str. That is, if you do:
String str = "xyz";
String otherStr = str;
String str = "abc";
Then otherStr will remain the same. So you're not actually changing the object that str points to.
As for your second question
String str = "xyz";
takes the a String-object with value "xyz" from the String pool, while
String str = new String("xyz");
instantiates a new object.
That is, if you do
String a = "xyz", b = "xyz";
you will have a == b, while if you do
String a = new String("xyz"), b = new String("xyz");
this will not be the case.example
For more information, see:
What is String literal pool?
Questions about Java's String pool
Strings are immutable. String references are not. That's the distinction.
So:
String str = "abc";
str is a variable, referring to an immutable string "abc". Now if I do:
str = "def";
str is still a variable, referring to a different immutable string ("def"). I can change what str points to all I want, str is a variable. I can't change the actual content of any string (because Java's strings are immutable, by design). Whenever you do something that would seem to modify the string (say, toUpperCase), what it's actually doing is creating a new string with a copy of the old string's contents, modified in the way described.
The point of having strings be immutable is that I know that if I have a reference to a string, that string can never change. This is a very useful guarantee when passing strings around. If we didn't have this guarantee, we'd be copying strings all the time just to protect ourselves from someone modifying them. For instance, consider a standard setter function for a name property:
void setName(String n) {
this.name = n;
}
If strings weren't immutable, we'd have to do this:
void setName(String n) {
this.name = new String(n); // Blech, duplication
}
...so that we know our copy of the string won't change in ways we don't expect it to. This would result in a lot of duplication of string data in memory, most of it unnecessary, and so the designers of Java quite intelligently decided that strings would be immutable, and any changes you might want would create a new string rather than modifying the old one in-place. (You can get modify-in-place behavior for those situations that really warrant it by using char[] instead.)
Regarding your separate question about the difference between str = "abc"; and str = new String("abc"), the difference is that the latter (using the constructor) is guaranteed to return a new reference, whereas the former is not. E.g.:
String a = "abc";
String b = "abc";
String c = new String("abc");
a == b (checking whether the references match, not the strings) will be true, because literal strings are interned. a == c is guaranteed to be false, because we used the constructor for c. a.equals(b) and a.equals(c) will both be true, because a, b, and c all refer to equivalent strings.
If Strings are immutable then below
statement should have compilation
error!
You are misunderstanding the immutability concept. Look at Prasoon's answer.
String immutability means you cannot alter the contents inside the string.
String a = "hello";
String b = "hello";
System.out.println(a==b); // returns true.
Here both a and b both string literals refer the same object.
What is the difference between two
instantiations ?
String a = "hello";
String b = "hello";
System.out.println(a==b); // returns true.
Both refer to same String literal.
String a = new String("hello");
String b = new String("hello");
System.out.println(a==b); // returns false.
Two different String Objects are created.
String str = "xyz";
is an internal cached string instance.
String str = new String("xyz");
is a new object not instanciated from the cache
As side fact notice the following behaviour ...
"xyz" == "xyz" evals true
new String("xyz") == new String("xyz") evals false
new String("xyz").equals(new String("xyz")) evals true
notice also that == in Java compares object references.

Immutability of Strings in Java

Consider the following example.
String str = new String();
str = "Hello";
System.out.println(str); //Prints Hello
str = "Help!";
System.out.println(str); //Prints Help!
Now, in Java, String objects are immutable. Then how come the object str can be assigned value "Help!". Isn't this contradicting the immutability of strings in Java? Can anybody please explain me the exact concept of immutability?
Edit:
Ok. I am now getting it, but just one follow-up question. What about the following code:
String str = "Mississippi";
System.out.println(str); // prints Mississippi
str = str.replace("i", "!");
System.out.println(str); // prints M!ss!ss!pp!
Does this mean that two objects are created again ("Mississippi" and "M!ss!ss!pp!") and the reference str points to a different object after replace() method?
str is not an object, it's a reference to an object. "Hello" and "Help!" are two distinct String objects. Thus, str points to a string. You can change what it points to, but not that which it points at.
Take this code, for example:
String s1 = "Hello";
String s2 = s1;
// s1 and s2 now point at the same string - "Hello"
Now, there is nothing1 we could do to s1 that would affect the value of s2. They refer to the same object - the string "Hello" - but that object is immutable and thus cannot be altered.
If we do something like this:
s1 = "Help!";
System.out.println(s2); // still prints "Hello"
Here we see the difference between mutating an object, and changing a reference. s2 still points to the same object as we initially set s1 to point to. Setting s1 to "Help!" only changes the reference, while the String object it originally referred to remains unchanged.
If strings were mutable, we could do something like this:
String s1 = "Hello";
String s2 = s1;
s1.setCharAt(1, 'a'); // Fictional method that sets character at a given pos in string
System.out.println(s2); // Prints "Hallo"
Edit to respond to OP's edit:
If you look at the source code for String.replace(char,char) (also available in src.zip in your JDK installation directory -- a pro tip is to look there whenever you wonder how something really works) you can see that what it does is the following:
If there is one or more occurrences of oldChar in the current string, make a copy of the current string where all occurrences of oldChar are replaced with newChar.
If the oldChar is not present in the current string, return the current string.
So yes, "Mississippi".replace('i', '!') creates a new String object. Again, the following holds:
String s1 = "Mississippi";
String s2 = s1;
s1 = s1.replace('i', '!');
System.out.println(s1); // Prints "M!ss!ss!pp!"
System.out.println(s2); // Prints "Mississippi"
System.out.println(s1 == s2); // Prints "false" as s1 and s2 are two different objects
Your homework for now is to see what the above code does if you change s1 = s1.replace('i', '!'); to s1 = s1.replace('Q', '!'); :)
1 Actually, it is possible to mutate strings (and other immutable objects). It requires reflection and is very, very dangerous and should never ever be used unless you're actually interested in destroying the program.
The object that str references can change, but the actual String objects themselves cannot.
The String objects containing the string "Hello" and "Help!" cannot change their values, hence they are immutable.
The immutability of String objects does not mean that the references pointing to the object cannot change.
One way that one can prevent the str reference from changing is to declare it as final:
final String STR = "Hello";
Now, trying to assign another String to STR will cause a compile error.
Light_handle I recommend you take a read of Cup Size -- a story about variables and Pass-by-Value Please (Cup Size continued). This will help a lot when reading the posts above.
Have you read them? Yes. Good.
String str = new String();
This creates a new "remote control" called "str" and sets that to the value new String() (or "").
e.g. in memory this creates:
str --- > ""
str = "Hello";
This then changes the remote control "str" but does not modify the original string "".
e.g. in memory this creates:
str -+ ""
+-> "Hello"
str = "Help!";
This then changes the remote control "str" but does not modify the original string "" or the object that the remote control currently points to.
e.g. in memory this creates:
str -+ ""
| "Hello"
+-> "Help!"
Lets break it into some parts
String s1 = "hello";
This Statement creates string containing hello and occupy space in memory i.e. in Constant String Pool and and assigned it to reference object s1
String s2 = s1;
This statement assigns the same string hello to new reference s2
__________
| |
s1 ---->| hello |<----- s2
|__________|
Both references are pointing to the same string so output the same value as follows.
out.println(s1); // o/p: hello
out.println(s2); // o/p: hello
Though String is immutable, assignment can be possible so the s1 will now refer to new value stack.
s1 = "stack";
__________
| |
s1 ---->| stack |
|__________|
But what about s2 object which is pointing to hello it will be as it is.
__________
| |
s2 ---->| hello |
|__________|
out.println(s1); // o/p: stack
out.println(s2); // o/p: hello
Since String is immutable Java Virtual Machine won't allow us to modify string s1 by its method. It will create all new String object in pool as follows.
s1.concat(" overflow");
___________________
| |
s1.concat ----> | stack overflow |
|___________________|
out.println(s1); // o/p: stack
out.println(s2); // o/p: hello
out.println(s1.concat); // o/p: stack overflow
Note if String would be mutable then the output would have been
out.println(s1); // o/p: stack overflow
Now you might be surprised why String has such methods like concat() to modify. Following snippet will clear your confusion.
s1 = s1.concat(" overflow");
Here we are assigning modified value of string back to s1 reference.
___________________
| |
s1 ---->| stack overflow |
|___________________|
out.println(s1); // o/p: stack overflow
out.println(s2); // o/p: hello
That's why Java decided String to be a final class Otherwise anyone can modify and change the value of string.
Hope this will help little bit.
The string object that was first referenced by str was not altered, all that you did was make str refer to a new string object.
The String will not change, the reference to it will. You are confusing immutability with the concept of final fields. If a field is declared as final, once it has been assigned, it cannot be reassigned.
Regarding the replace part of your question, try this:
String str = "Mississippi";
System.out.println(str); //Prints Mississippi
String other = str.replace("i", "!");
System.out.println(str); //still prints Mississippi
System.out.println(other); // prints M!ss!ss!pp!
Though java tries to ignore it, str is nothing more than a pointer. This means that when you first write str = "Hello";, you create an object that str points to. When you reassign str by writing str = "Help!";, a new object is created and the old "Hello" object gets garbage collected whenever java feels like it.
Immutability implies that the value of an instantiated object cannot change, you can never turn "Hello" into "Help!".
The variable str is a reference to an object, when you assign a new value to str you aren't changing the value of the object it references, you are referencing a different object.
String class is immutable, and you can not change value of immutable object.
But in case of String, if you change the value of string than it will create new string in string pool and than your string reference to that value not the older one. so by this way string is immutable.
Lets take your example,
String str = "Mississippi";
System.out.println(str); // prints Mississippi
it will create one string "Mississippi" and will add it to String pool
so now str is pointing to Mississippi.
str = str.replace("i", "!");
System.out.println(str); // prints M!ss!ss!pp!
But after above operation,
one another string will be created "M!ss!ss!pp!"
and it will be add to String pool. and
now str is pointing to M!ss!ss!pp!, not Mississippi.
so by this way when you will alter value of string object it will create one more object and will add it to string pool.
Lets have one more example
String s1 = "Hello";
String s2 = "World";
String s = s1 + s2;
this above three line will add three objects of string to string pool.
1) Hello
2) World
3) HelloWorld
For those wondering how to break String immutability in Java...
Code
import java.lang.reflect.Field;
public class StringImmutability {
public static void main(String[] args) {
String str1 = "I am immutable";
String str2 = str1;
try {
Class str1Class = str1.getClass();
Field str1Field = str1Class.getDeclaredField("value");
str1Field.setAccessible(true);
char[] valueChars = (char[]) str1Field.get(str1);
valueChars[5] = ' ';
valueChars[6] = ' ';
System.out.println(str1 == str2);
System.out.println(str1);
System.out.println(str2);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
Output
true
I am mutable
I am mutable
Use:
String s = new String("New String");
s.concat(" Added String");
System.out.println("String reference -----> "+s); // Output: String reference -----> New String
If you see here I use the concat method to change the original string, that is, "New String" with a string " Added String", but still I got the output as previous, hence it proves that you can not change the reference of object of String class, but if you do this thing by StringBuilder class it will work. It is listed below.
StringBuilder sb = new StringBuilder("New String");
sb.append(" Added String");
System.out.println("StringBuilder reference -----> "+sb);// Output: StringBuilder reference -----> New String Added String
Like Linus Tolvards said:
Talk is cheap. Show me the code
Take a look at this:
public class Test{
public static void main(String[] args){
String a = "Mississippi";
String b = "Mississippi";//String immutable property (same chars sequence), then same object
String c = a.replace('i','I').replace('I','i');//This method creates a new String, then new object
String d = b.replace('i','I').replace('I','i');//At this moment we have 3 String objects, a/b, c and d
String e = a.replace('i','i');//If the arguments are the same, the object is not affected, then returns same object
System.out.println( "a==b? " + (a==b) ); // Prints true, they are pointing to the same String object
System.out.println( "a: " + a );
System.out.println( "b: " + b );
System.out.println( "c==d? " + (c==d) ); // Prints false, a new object was created on each one
System.out.println( "c: " + c ); // Even the sequence of chars are the same, the object is different
System.out.println( "d: " + d );
System.out.println( "a==e? " + (a==e) ); // Same object, immutable property
}
}
The output is
a==b? true
a: Mississippi
b: Mississippi
c==d? false
c: Mississippi
d: Mississippi
a==e? true
So, remember two things:
Strings are immutable until you apply a method that manipulates and creates a new one (c & d cases).
Replace method returns the same String object if both parameters are the same
String is immutable. Which means that we can only change the reference.
String a = "a";
System.out.println("String a is referencing to "+a); // Output: a
a.concat("b");
System.out.println("String a is referencing to "+a); // Output: a
a = a.concat("b");
System.out.println("String a has created a new reference and is now referencing to "+a); // Output: ab
In Java, objects are generally accessed by references. In your piece of code str is a reference which is first assigned to "Hello" (an automatic created object or fetched from constant pool) and then you assigned another object "Help!" to same reference. A point to note is the reference is the same and modified, but objects are different. One more thing in your code you accessed three objects,
When you called new String().
When you assigned "hello".
When you assigned "help!".
Calling new String() creates a new object even if it exists in string pool, so generally it should not be used. To put a string created from new String () into string pool you can try the intern() method.
I hope this helps.
Immutability I can say is that you cannot change the String itself. Suppose you have String x, the value of which is "abc". Now you cannot change the String, that is, you cannot change any character/s in "abc".
If you have to change any character/s in the String, you can use a character array and mutate it or use StringBuilder.
String x = "abc";
x = "pot";
x = x + "hj";
x = x.substring(3);
System.out.println(x);
char x1[] = x.toCharArray();
x1[0] = 's';
String y = new String(x1);
System.out.println(y);
Output:
hj
sj
Or you can try:
public class Tester
{
public static void main(String[] args)
{
String str = "Mississippi";
System.out.println(str); // prints Mississippi
System.out.println(str.hashCode());
str = str.replace("i", "!");
System.out.println(str); // prints M!ss!ss!pp!
System.out.println(str.hashCode());
}
}
This will show how the hashcode changes.
String is immutable means that you cannot change the object itself, but you can change the reference to the object. When you called a = "ty", you are actually changing the reference of a to a new object created by the String literal "ty". Changing an object means to use its methods to change one of its fields (or the fields are public and not final, so that they can be updated from outside without accessing them via methods), for example:
Foo x = new Foo("the field");
x.setField("a new field");
System.out.println(x.getField()); // prints "a new field"
While in an immutable class (declared as final, to prevent modification via inheritance)(its methods cannot modify its fields, and also the fields are always private and recommended to be final), for example String, you cannot change the current String but you can return a new String, i.e:
String s = "some text";
s.substring(0,4);
System.out.println(s); // still printing "some text"
String a = s.substring(0,4);
System.out.println(a); // prints "some"
Here immutability means that instance can point to other reference but the original content of the string would not be modified at the original reference.
Let me explain by first example given by you.
First str is pointing to "Hello" ,its Ok upto this.
Second time its pointing to "Help!".
Here str started pointing to "Help!" and the reference of "Hello" string is lost and we can not get that back.
In fact when str would try to modify the existing content,then another new string will be generated and str will start to point at that reference.
So we see that string at original reference is not modified but that is safe at its reference and instance of object started pointing at different reference so immutability is conserve.
Super late to the answer, but wanted to put a concise message from author of the String class in Java
Strings are constant; their values cannot be changed after they are
created. String buffers support mutable strings. Because String
objects are immutable they can be shared.
It can be derived from this documentation that anything that changes string, returns different object (which could be new or interned and old).
The not so subtle hint about this should come from the function signature.
Think about it, 'Why did they make a function on an object return an object instead of status?'.
public String replace(char oldChar, char newChar)
Also one more source which makes this behaviour explicit (From replace function documentation)
Returns a new string resulting from replacing all occurrences of
oldChar in this string with newChar.
Source: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replace(char,%20char)
author Lee Boynton
author Arthur van Hoff
author Martin Buchholz
author Ulf Zibis
Source: JavaDoc of String.
The Object string - methods itself is made to be "immutable".
This action produces no changes: "letters.replace("bbb", "aaa");"
But assigning data does cause changes to the Strings content to change:
letters = "aaa";
letters=null;
System.out.println(letters);
System.out.println(oB.hashCode());
System.out.println(letters);
letters = "bbbaaa";
System.out.println(oB.hashCode());
System.out.println(letters);
//The hashcode of the string Object doesn't change.
If HELLO is your String then you can't change HELLO to HILLO. This property is called immutability property.
You can have multiple pointer String variable to point HELLO String.
But if HELLO is char Array then you can change HELLO to HILLO. Eg,
char[] charArr = 'HELLO';
char[1] = 'I'; //you can do this
Programming languages have immutable data variables so that it can be used as keys in key, value pair.
I would explain it with simple example
consider any character array : e.g. char a[]={'h','e','l','l','o'};
and a string :
String s="hello";
on character array we can perform operations like printing only last three letters using iterating the array;
but in string we have to make new String object and copy required substring and its address will be in new string object.
e.g.
***String s="hello";
String s2=s.substrig(0,3);***
so s2 will have "hel";
String in Java in Immutable and Final just mean it can't be changed or modified:
Case 1:
class TestClass{
public static void main(String args[]){
String str = "ABC";
str.concat("DEF");
System.out.println(str);
}
}
Output: ABC
Reason: The object reference str is not changed in fact a new object
"DEF" is created which is in the pool and have no reference at all
(i.e lost).
Case 2:
class TestClass{
public static void main(String args[]){
String str="ABC";
str=str.concat("DEF");
System.out.println(str);
}
}
Output: ABCDEF
Reason: In this case str is now referring to a new object "ABCDEF"
hence it prints ABCDEF i.e. previous str object "ABC" is lost in pool with no reference.
Because String is immutable so changes will not occur if you will not assign the returned value of function to the string.so in your question assign value of swap function  returned value to s.
s=swap(s, n1, n2) ;then the value of string s will change.
I was also getting the unchanged value when i was writing the program to get some permutations string(Although it is not giving all the permutations but this is for example to answer your question)
Here is a example.
> import java.io.*;  public class MyString { public static void
> main(String []args)throws IOException {  BufferedReader br=new
> BufferedReader(new InputStreamReader(System.in));  String
> s=br.readLine().trim(); int n=0;int k=0;  while(n!=s.length()) {
> while(k<n){  swap(s,k,n); System.out.println(s); swap(s,k,n); k++; }
> n++; } }  public static void swap(String s,int n1,int n2) { char temp;
> temp=s.charAt(n1); StringBuilder sb=new StringBuilder(s);
> sb.setCharAt(n1,s.charAt(n2)); sb.setCharAt(n2,temp); s=sb.toString();
> } }
but i was not getting the permuted values of the string from above code.So I assigned the returned value of the swap function to the string and got changed values of string. after assigning the returned value i got the permuted values of string.
/import java.util.*; import java.io.*; public class MyString { public static void main(String []args)throws IOException{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 
String s=br.readLine().trim(); int n=0;int k=0; 
while(n!=s.length()){ while(k<n){ s=swap(s,k,n); 
System.out.println(s); s=swap(s,k,n); k++; } n++; } } 
public static String swap(String s,int n1,int n2){
char temp; temp=s.charAt(n1); StringBuilder sb=new StringBuilder(s); sb.setCharAt(n1,s.charAt(n2)); sb.setCharAt(n2,temp); s=sb.toString(); return s; } }
public final class String_Test {
String name;
List<String> list=new ArrayList<String>();
public static void main(String[] args) {
String_Test obj=new String_Test();
obj.list.add("item");//List will point to a memory unit- i.e will have one Hashcode value #1234
List<String> list2=obj.list; //lis1 also will point to same #1234
obj.list.add("new item");//Hashcode of list is not altered- List is mutable, so reference remains same, only value in that memory location changes
String name2=obj.name="Myname"; // name2 and name will point to same instance of string -Hashcode #5678
obj.name = "second name";// String is Immutable- New String HAI is created and name will point to this new instance- bcoz of this Hashcode changes here #0089
System.out.println(obj.list.hashCode());
System.out.println(list2.hashCode());
System.out.println(list3.hashCode());
System.out.println("===========");
System.out.println(obj.name.hashCode());
System.out.println(name2.hashCode());
}
}
Will produce out put something like this
1419358369
1419358369
103056
65078777
Purpose of Immutable object is that its value should not be altered once assigned.
It will return new object everytime you try to alter it based on the implementation.
Note: Stringbuffer instead of string can be used to avoid this.
To your last question :: u will have one reference , and 2 strings in string pool..
Except the reference will point to m!ss!ss!pp!

Categories