how are String objects immutable in this case? - java

I agree with the fact that the String objects are immutable, means they cannot be modified. Like in the case below
String str = "Hi";
String str1 = str.concat("Nilesh");
Here the str object will be returned if the length argument is 0 or a new String object will be created and its reference will be returned.
And if i do
String str = "Hi";
str="Hello";
How is it getting changed? where does immutable comes into picture? An example please.

What is immutable is the String itself, not the reference that points to the String. In your second code:
String str = "hi";
str = "hello";
There are 2 String objects involved: "hi" and "hello".
str is a reference that originally points to the first one then points to the second one following an assignment. But the String object "hi" does not get modified in that code.

You are confusing immutability with changing the reference.
This code:
String str = "Hi"; // str now refers to the String "Hi"
str = "Hello"; // str now refers to the String "Hello"
just changes the String object to which str refers; str is a variable that holds a reference to a String object. Nothing happened to mutate either the "Hi" or the "Hello" object.
If String were mutable, it would have a method like setValue(String s) that could be called to alter its state, so you might be able to do this:
String str = "Hi";
str.setValue("Hello"); // if String were mutable

"Hello" is completely different object of String so you can no longer refer to "Hi"
Immutability is not about Reference it is about object state. If state is changed new object is created.
http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html
An object is considered immutable if its state cannot change after it is constructed.

str is a variable. The term "variable" means that the variable may be assigned various strings, one at a time. Each string is still immutable.

If the others said "Hello" is another String. I think you can see the fact that is a new String best when using System.identityHashCode(). Just try it out:
String str = "Hi";
System.out.println("try 1: "+System.identityHashCode(str));
str="Hello";
System.out.println("try 2: "+System.identityHashCode(str));
System.identityHashCode will usually return the reference itself (but you cannot rely on that fact).

String str = "Hi";
str="Hello";
String is immutable so we cant modify the String Object.
Here, Two object will be created, We can verify through hashcode.
String str = "Hi";
System.out.println("Str(Hi)-hashcode: "+str.hashCode());
str="Hello";
System.out.println("Str(Hello)-hashcode: "+str.hashCode());
In Both cases HashCode value will be different.
1st case-> Str(Hi)-hashcode: 2337
2nd case-> Str(Hello)-hashcode: 69609650

case 1:
String str = "Hi";
String str1 = str.concat("Nilesh");
total of 3 string objects are created
case 2:
String str = "Hi";
str="Hello";
in this case 2 string objects are created.
when line 1 is executed str referes to "Hi".
when line 2 is executed str refers to "Hello" and isolates "Hi".
str just refers to "Hello" after line2

Related

Why should I remove String constructor invocation? [duplicate]

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!

What is difference between mutable and immutable String in java

As per my knowledge,
a mutable string can be changed, and
an immutable string cannot be changed.
Here I want to change the value of String like this,
String str="Good";
str=str+" Morning";
and other way is,
StringBuffer str= new StringBuffer("Good");
str.append(" Morning");
In both the cases I am trying to alter the value of str. Can anyone tell me, what is difference in both case and give me clear picture of mutable and immutable objects.
Case 1:
String str = "Good";
str = str + " Morning";
In the above code you create 3 String Objects.
"Good" it goes into the String Pool.
" Morning" it goes into the String Pool as well.
"Good Morning" created by concatenating "Good" and " Morning". This guy goes on the Heap.
Note: Strings are always immutable. There is no, such thing as a mutable String. str is just a reference which eventually points to "Good Morning". You are actually, not working on 1 object. you have 3 distinct String Objects.
Case 2:
StringBuffer str = new StringBuffer("Good");
str.append(" Morning");
StringBuffer contains an array of characters. It is not same as a String.
The above code adds characters to the existing array. Effectively, StringBuffer is mutable, its String representation isn't.
What is difference between mutable and immutable String in java
immutable exist, mutable don't.
In Java, all strings are immutable. When you are trying to modify a String, what you are really doing is creating a new one. However, when you use a StringBuilder, you are actually modifying the contents, instead of creating a new one.
Java Strings are immutable.
In your first example, you are changing the reference to the String, thus assigning it the value of two other Strings combined: str + " Morning".
On the contrary, a StringBuilder or StringBuffer can be modified through its methods.
Mutable :- Changeable
Immutable :- Unchangeable
String in Java is immutable. However what does it mean to be mutable in programming context is the first question. Consider following class,
public class Dimension {
private int height;
private int width;
public Dimenstion() {
}
public void setSize(int height, int width) {
this.height = height;
this.width = width;
}
public getHeight() {
return height;
}
public getWidth() {
return width;
}
}
Now after creating the instance of Dimension we can always update it's attributes. Note that if any of the attribute, in other sense state, can be updated for instance of the class then it is said to be mutable. We can always do following,
Dimension d = new Dimension();
d.setSize(10, 20);// Dimension changed
d.setSize(10, 200);// Dimension changed
d.setSize(100, 200);// Dimension changed
Let's see in different ways we can create a String in Java.
String str1 = "Hey!";
String str2 = "Jack";
String str3 = new String("Hey Jack!");
String str4 = new String(new char[] {'H', 'e', 'y', '!'});
String str5 = str1 + str2;
str1 = "Hi !";
// ...
So,
str1 and str2 are String literals which gets created in String constant pool
str3, str4 and str5 are String Objects which are placed in Heap memory
str1 = "Hi!"; creates "Hi!" in String constant pool and it's totally different reference than "Hey!" which str1 referencing earlier.
Here we are creating the String literal or String Object. Both are different, I would suggest you to read following post to understand more about it.
Difference between string object and string literal
In any String declaration, one thing is common, that it does not modify but it gets created or shifted to other.
String str = "Good"; // Create the String literal in String pool
str = str + " Morning"; // Create String with concatenation of str + "Morning"
|_____________________|
|- Step 1 : Concatenate "Good" and " Morning" with StringBuilder
|- Step 2 : assign reference of created "Good Morning" String Object to str
How String became immutable ?
It's non changing behaviour, means, the value once assigned can not be updated in any other way. String class internally holds data in character array. Moreover, class is created to be immutable. Take a look at this strategy for defining immutable class.
Shifting the reference does not mean you changed it's value. It would be mutable if you can update the character array which is behind the scene in String class. But in reality that array will be initialized once and throughout the program it remains the same.
Why StringBuffer is mutable ?
As you already guessed, StringBuffer class is mutable itself as you can update it's state directly. Similar to String it also holds value in character array and you can manipulate that array by different methods i.e. append, delete, insert etc. which directly changes the character value array.
When you say str, you should be careful what you mean:
do you mean the variable str?
or do you mean the object referenced by str?
In your StringBuffer example you are not altering the value of str, and in your String example you are not altering the state of the String object.
The most poignant way to experience the difference would be something like this:
static void change(String in) {
in = in + " changed";
}
static void change(StringBuffer in) {
in.append(" changed");
}
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("value");
String str = "value";
change(sb);
change(str);
System.out.println("StringBuffer: "+sb);
System.out.println("String: "+str);
}
In Java, all strings are immutable(Can't change). When you are trying to modify a String, what you are really doing is creating a new one.
Following ways we can create the string object
Using String literal
String str="java";
Using new keyword
String str = new String("java");
Using character array
char[] helloArray = { 'h', 'e', 'l', 'l', 'o', '.' };
String helloString = new String(helloArray);
coming to String immutability, simply means unmodifiable or unchangeable
Let's take one example
I'm initializing the value to the String literal s
String s="kumar";
Below I'm going to display the decimal representation of the location address using hashcode()
System.out.println(s.hashCode());
Simply printing the value of a String s
System.out.println("value "+s);
Okay, this time I'm inittializing value "kumar" to s1
String s1="kumar"; // what you think is this line, takes new location in the memory ???
Okay let's check by displaying hashcode of the s1 object which we created
System.out.println(s1.hashCode());
okay, let's check below code
String s2=new String("Kumar");
System.out.println(s2.hashCode()); // why this gives the different address ??
Okay, check this below code at last
String s3=new String("KUMAR");
System.out.println(s3.hashCode()); // again different address ???
YES, if you see Strings 's' and 's1' having the same hashcode because the value hold by 's' & 's1' are same that is 'kumar'
Let's consider String 's2' and 's3' these two Strings hashcode appears to be different in the sense, they both stored in a different location because you see their values are different.
since s and s1 hashcode is same because those values are same and storing in the same location.
Example 1:
Try below code and analyze line by line
public class StringImmutable {
public static void main(String[] args) {
String s="java";
System.out.println(s.hashCode());
String s1="javA";
System.out.println(s1.hashCode());
String s2=new String("Java");
System.out.println(s2.hashCode());
String s3=new String("JAVA");
System.out.println(s3.hashCode());
}
}
Example 2: Try below code and analyze line by line
public class StringImmutable {
public static void main(String[] args) {
String s="java";
s.concat(" programming"); // s can not be changed "immutablity"
System.out.println("value of s "+s);
System.out.println(" hashcode of s "+s.hashCode());
String s1="java";
String s2=s.concat(" programming"); // s1 can not be changed "immutablity" rather creates object s2
System.out.println("value of s1 "+s1);
System.out.println(" hashcode of s1 "+s1.hashCode());
System.out.println("value of s2 "+s2);
System.out.println(" hashcode of s2 "+s2.hashCode());
}
}
Okay, Let's look what is the difference between mutable and immutable.
mutable(it change) vs. immutable (it can't change)
public class StringMutableANDimmutable {
public static void main(String[] args) {
// it demonstrates immutable concept
String s="java";
s.concat(" programming"); // s can not be changed (immutablity)
System.out.println("value of s == "+s);
System.out.println(" hashcode of s == "+s.hashCode()+"\n\n");
// it demonstrates mutable concept
StringBuffer s1= new StringBuffer("java");
s1.append(" programming"); // s can be changed (mutablity)
System.out.println("value of s1 == "+s1);
System.out.println(" hashcode of s1 == "+s1.hashCode());
}
}
Any further questions?? please write on...
I modified the code of william with a output comments for better understandable
static void changeStr(String in) {
in = in+" changed";
System.out.println("fun:"+in); //value changed
}
static void changeStrBuf(StringBuffer in) {
in.append(" changed"); //value changed
}
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("value");
String str = "value";
changeStrBuf(sb);
changeStr(str);
System.out.println("StringBuffer: "+sb); //value changed
System.out.println("String: "+str); // value
}
In above code , look at the value of str in both main() and changeStr() , even though u r changing the value of str in changeStr() it is affecting only to that function but in the main function the value is not changed , but it not in the case of StringBuffer..
In StringBuffer changed value is affected as a global..
hence String is immutable and StringBuffer is mutable...
In Simple , whatever u changed to String Object will affecting only to that function By going to String Pool. but not Changed...
A mutable variable is one whose value may change in place, whereas in an immutable variable change of value will not happen in place. Modifying an immutable variable will rebuild the same variable.
Mutable means you will save the same reference to variable and change its contents but immutable you can not change contents but you will declare new reference contains the new and the old value of the variable
Ex
Immutable -> String
String x = "value0ne";// adresse one
x += "valueTwo"; //an other adresse {adresse two}
adresse on the heap memory change.
Mutable -> StringBuffer - StringBuilder
StringBuilder sb = new StringBuilder();
sb.append("valueOne"); // adresse One
sb.append("valueTwo"); // adresse One
sb still in the same adresse i hope this comment helps

How does Java String remove all non numeric work internally? [duplicate]

This question already has answers here:
Immutability of Strings in Java
(26 answers)
Closed 9 years ago.
Since string is immutable I have to write as follows to remove all non-alphanemeric from the str.
void test(String str) {
str = str.replaceAll("[^a-zA-Z0-9\\s]", "").toLowerCase();
System.out.println("\n" +str);
}
What I couldn't understand is that how come it works by re-assigning to str?
Since String is immutable, I understand that if I assign it to a new String newString, they are pointing out two different objects, str and newString.
That it, original string is pointing to str and modified string is pointing ot newStr which have two different immutable Strings. This is ok for me.
void test(String str) {
String newStr = str.replaceAll("[^a-zA-Z0-9\\s]", "").toLowerCase();
System.out.println("\n" +newStr);
}
But how come it works by reassigning to the same str object? Based on my understanding, it shouldn't be working since immutable str cannot me modified, so the result of the modified str cannot be stored in immutable str.
void test(String str) {
// this shouldn't be working based on my understanding. But it works. Why?
str = str.replaceAll("[^a-zA-Z0-9\\s]", "").toLowerCase();
System.out.println("\n" +str);
}
As you've seen the following image, string1 and string2 are pointing to the same String object in the heap. Could you clarify how this works internally?
You aren't assigning to the same str object.
Take a look at the replaceAll etc methods and you will see that they return String, that is a new String object that the replaceAll method has created.
So str=str.replaceAll() takes your String reference from str, calls replaceAll() in that String. replaceAll processes this and then returns a new String object with the results of that processing. You then assign that back into the original reference.
You need to understand references: str is a reference to a certain area in your memory. What's happening is, the Java runtime creates a new memory area with the string where all the characters are removed and then "points" str to the new memory area.
This is not the same as modifying the memory area the str already points to.
"Immutability" means that the memory area a variable points to can not be modified. The content is fixed. To "modify" it, memory must be copied, modified and then be reassigned.
"Mutable" objects can modify data in memory without copying the old data to a new memory area.
By the way, in our example, the string is even copied twice!
First time, this copyies the string:
replaceAll("[^a-zA-Z0-9\\s]", "")
Then another copy is created by
toLowerCase()
which is then finally assigned to your variable.
Your code is thus equal to the following:
void test(String str)
{
String str1 = str.replaceAll("[^a-zA-Z0-9\\s]", "");
String str2 = str1.toLowerCase();
str = str2;
System.out.println("\n" +str);
}
You need to understand that in Java, variables are not objects; variables are references to objects.
So, str is not a String object, it is a reference to a String object. "Immutable" means that the content of the object that the variable is referring to cannot be changed; it does not mean that the variable itself cannot be changed to refer to a different object.
You're making str point to a different String object; namely, the new String object that str.replaceAll returns.

String is immutable. What exactly is the meaning? [duplicate]

This question already has answers here:
Immutability of Strings in Java
(26 answers)
Closed 7 years ago.
I wrote the following code on immutable Strings.
public class ImmutableStrings {
public static void main(String[] args) {
testmethod();
}
private static void testmethod() {
String a = "a";
System.out.println("a 1-->" + a);
a = "ty";
System.out.println("a 2-->" + a);
}
}
Output:
a 1-->a
a 2-->ty
Here the value of variable a has been changed (while many say that contents of the immutable objects cannot be changed). But what exactly does one mean by saying String is immutable? Could you please clarify this topic for me?
source : https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
Before proceeding further with the fuss of immutability, let's just take a look into the String class and its functionality a little before coming to any conclusion.
This is how String works:
String str = "knowledge";
This, as usual, creates a string containing "knowledge" and assigns it a reference str. Simple enough? Lets perform some more functions:
String s = str; // assigns a new reference to the same string "knowledge"
Lets see how the below statement works:
str = str.concat(" base");
This appends a string " base" to str. But wait, how is this possible, since String objects are immutable? Well to your surprise, it is.
When the above statement is executed, the VM takes the value of String str, i.e. "knowledge" and appends " base", giving us the value "knowledge base". Now, since Strings are immutable, the VM can't assign this value to str, so it creates a new String object, gives it a value "knowledge base", and gives it a reference str.
An important point to note here is that, while the String object is immutable, its reference variable is not. So that's why, in the above example, the reference was made to refer to a newly formed String object.
At this point in the example above, we have two String objects: the first one we created with value "knowledge", pointed to by s, and the second one "knowledge base", pointed to by str. But, technically, we have three String objects, the third one being the literal "base" in the concat statement.
Important Facts about String and Memory usage
What if we didn't have another reference s to "knowledge"? We would have lost that String. However, it still would have existed, but would be considered lost due to having no references.
Look at one more example below
String s1 = "java";
s1.concat(" rules");
System.out.println("s1 refers to "+s1); // Yes, s1 still refers to "java"
What's happening:
The first line is pretty straightforward: create a new String "java" and refer s1 to it.
Next, the VM creates another new String "java rules", but nothing
refers to it. So, the second String is instantly lost. We can't reach
it.
The reference variable s1 still refers to the original String "java".
Almost every method, applied to a String object in order to modify it, creates new String object. So, where do these String objects go? Well, these exist in memory, and one of the key goals of any programming language is to make efficient use of memory.
As applications grow, it's very common for String literals to occupy large area of memory, which can even cause redundancy. So, in order to make Java more efficient, the JVM sets aside a special area of memory called the "String constant pool".
When the compiler sees a String literal, it looks for the String in the pool. If a match is found, the reference to the new literal is directed to the existing String and no new String object is created. The existing String simply has one more reference. Here comes the point of making String objects immutable:
In the String constant pool, a String object is likely to have one or many references. If several references point to same String without even knowing it, it would be bad if one of the references modified that String value. That's why String objects are immutable.
Well, now you could say, what if someone overrides the functionality of String class? That's the reason that the String class is marked final so that nobody can override the behavior of its methods.
String is immutable means that you cannot change the object itself, but you can change the reference to the object.
When you execute 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"
You're changing what a refers to. Try this:
String a="a";
System.out.println("a 1-->"+a);
String b=a;
a="ty";
System.out.println("a 2-->"+a);
System.out.println("b -->"+b);
You will see that the object to which a and then b refers has not changed.
If you want to prevent your code from changing which object a refers to, try:
final String a="a";
A string is a char[] containing a series of UTF-16 code units, an int offset into that array, and an int length.
For example.
String s
It creates space for a string reference. Assigning copies references around but does not modify the objects to which those references refer.
You should also be aware that
new String(s)
doesn't really do anything useful. It merely creates another instance backed by the same array, offset, and length as s. There is very rarely a reason to do this so it is considered bad practice by most Java programmers.
Java double quoted strings like "my string" are really references to interned String instances so "bar" is a reference to the same String instance regardless of how many times it appears in your code.
The "hello" creates one instance that is pooled, and the new String(...) creates a non-pooled instance. Try System.out.println(("hello" == "hello") + "," + (new String("hello") == "hello") + "," + (new String("hello") == new String("hello"))); and you should see true,false,false
immutable means you can't not change the value of the same referance.every time you required to create new referance means new memory location.
ex:
String str="abc";
str="bcd";
here, in the above code ,in the memory there are 2 blocks for storing the value.the first for value "abc" and second for "bcd".the second value is not replace to first value.
this is call the immutable.
In your example, the variable a is just a reference to an instance of a string object. When you say a = "ty", you are not actually changing the string object, but rather pointing the reference at an entirely different instance of the string class.
see here
class ImmutableStrings {
public static void main(String[] args) {
testmethod();
}
private static void testmethod() {
String a="a";
System.out.println("a 1-->"+a);
System.out.println("a 1 address-->"+a.hashCode());
a = "ty";
System.out.println("a 2-->"+a);
System.out.println("a 2 address-->"+a.hashCode());
}
}
output:
a 1-->a
a 1 address-->97
a 2-->ty
a 2 address-->3717
This indicates that whenever you are modifying the content of immutable string object a a new object will be created. i.e you are not allowed to change the content of immutable object. that's why the address are different for both the object.
You are not changing the object in the assignment statement, you replace one immutable object with another one. Object String("a") does not change to String("ty"), it gets discarded, and a reference to ty gets written into a in its stead.
In contrast, StringBuffer represents a mutable object. You can do this:
StringBuffer b = new StringBuffer("Hello");
System.out.writeln(b);
b.append(", world!");
System.out.writeln(b);
Here, you did not re-assign b: it still points to the same object, but the content of that object has changed.
You are actually getting a reference to a new string, the string itself is not being changed as it is immutable. This is relevant.
See
Immutable objects on Wikipedia
An immutable object is an object whose state cannot be modified after it is created.
So a = "ABC" <-- immutable object. "a" holds reference to the object.
And, a = "DEF" <-- another immutable object, "a" holds reference to it now.
Once you assign a string object, that object can not be changed in memory.
In summary, what you did is to change the reference of "a" to a new string object.
String S1="abc";
S1.concat("xyz");
System.out.println("S1 is", + S1);
String S2=S1.concat("def");
System.out.println("S2 is", + S2);
This shows that once a string object is create it cannot be changed. EveryTime you need to create new and put in another String. S
I think the following code clears the difference:
String A = new String("Venugopal");
String B = A;
A = A +"mitul";
System.out.println("A is " + A);
System.out.println("B is " + B);
StringBuffer SA = new StringBuffer("Venugopal");
StringBuffer SB = SA;
SA = SA.append("mitul");
System.out.println("SA is " + SA);
System.out.println("SB is " + SB);
Java String is immutable, String will Store the value in the form of object. so if u assign the value String a="a"; it will create an object and the value is stored in that and again if you are assigning value a="ty" means it will create an another object store the value in that, if you want to understand clearly, check the has code for the String.
Only the reference is changing. First a was referencing to the string "a", and later you changed it to "ty". The string "a" remains the same.
In your example, a refers first to "a", and then to "ty". You're not mutating any String instance; you're just changing which String instance a refers to. For example, this:
String a = "a";
String b = a; // b refers to the same String as a
a = "b"; // a now refers to a different instance
System.out.println(b);
prints "a", because we never mutate the String instance that b points to.
If some object bar holds a reference to a mutable object foo and encapsulates some of its state in mutable aspects of foo's state, that will allow code which can change those aspects of foo to change the corresponding aspects of bar's state without actually touching bar or even knowing of its existence. Generally, this means that objects which encapsulate their own state using mutable objects must ensure that no references to those objects are exposed to any code which might unexpectedly mutate them. By contrast, if bar holds a reference to an object moo and only uses immutable aspects of moo other than identity to encapsulate its state, then bar can freely expose moo to outside code without worrying about anything the outside code might do to it.
Hope the below code would clarify your doubts :
public static void testString() {
String str = "Hello";
System.out.println("Before String Concat: "+str);
str.concat("World");
System.out.println("After String Concat: "+str);
StringBuffer sb = new StringBuffer("Hello");
System.out.println("Before StringBuffer Append: "+sb);
sb.append("World");
System.out.println("After StringBuffer Append: "+sb);
}
Before String Concat: Hello
After String Concat: Hello
Before StringBuffer Append: Hello
After StringBuffer Append: HelloWorld
Probably every answer provided above is right, but my answer is specific to use of hashCode() method, to prove the points like, String... once created can't be modified and modifications will results in new value at different memory location.
public class ImmutabilityTest {
private String changingRef = "TEST_STRING";
public static void main(String a[]) {
ImmutabilityTest dn = new ImmutabilityTest();
System.out.println("ChangingRef for TEST_STRING OLD : "
+ dn.changingRef.hashCode());
dn.changingRef = "NEW_TEST_STRING";
System.out.println("ChangingRef for NEW_TEST_STRING : "
+ dn.changingRef.hashCode());
dn.changingRef = "TEST_STRING";
System.out.println("ChangingRef for TEST_STRING BACK : "
+ dn.changingRef.hashCode());
dn.changingRef = "NEW_TEST_STRING";
System.out.println("ChangingRef for NEW_TEST_STRING BACK : "
+ dn.changingRef.hashCode());
String str = new String("STRING1");
System.out.println("String Class STRING1 : " + str.hashCode());
str = new String("STRING2");
System.out.println("String Class STRING2 : " + str.hashCode());
str = new String("STRING1");
System.out.println("String Class STRING1 BACK : " + str.hashCode());
str = new String("STRING2");
System.out.println("String Class STRING2 BACK : " + str.hashCode());
}
}
OUTPUT
ChangingRef for TEST_STRING OLD : 247540830
ChangingRef for NEW_TEST_STRING : 970356767
ChangingRef for TEST_STRING BACK : 247540830
ChangingRef for NEW_TEST_STRING BACK : 970356767
String Class STRING1 : -1163776448
String Class STRING2 : -1163776447
String Class STRING1 BACK : -1163776448
String Class STRING2 BACK : -1163776447
String is immutable it means that,the content of the String Object can't be change, once it is created. If you want to modify the content then you can go for StringBuffer/StringBuilder instead of String. StringBuffer and StringBuilder are mutable classes.

Why does the following example seem to refute that Strings are immutable objects in Java?

I am using the OpenJDK Java compiler under Ubuntu. I wanted to convert a character array to a string and when that seemed to have ended up giving ambiguous results, I tried to write a toString method of my own. In the process, I wrote a test program wherein (out of the fun of it) I tried to compile the following code.
class toString{
public static void main(String[] args){
string = "abc";
string = string + "bcd";
System.out.println(string);
}
}
Now, I know that String objects in Java are immutable and the code should have in fact generated an error but to my surprise, it printed abcbcd to the console. Does this mean that String objects in Java are mutable or is there something wrong with the implementation of OpenJDK compiler in this case?
The code that you've posted above does not actually mutate any strings, though it looks like it does. The reason is that this line doesn't mutate the string:
string = string + "bcd";
Instead, what this does is:
Construct a new string whose value is string + "bcd".
Change what string is referenced by string to refer to this new string.
In other words, the actual concrete string objects themselves weren't changed, but the references to those strings were indeed modified. Immutability in Java usually means that objects cannot be modified, not the references to those objects.
An important detail that confuses a lot of new Java programmers is that the above line is often written as
string += "bcd";
which looks even more strongly as though it's concatenating bcd onto the end of the string and thereby mutating it, even though it's equivalent to the above code and therefore doesn't cause any changes to the actual String object (again, it works by creating a new String object and changing what object the reference refers to.)
To see that what's going on here is that you're actually changing the reference and not the string it refers to, you can try rewriting the code to make string final, which prevents you from changing what object is referenced. If you do so, you'll find that the code no longer compiles. For example:
class toString{
public static void main(String[] args){
final String string = "abc";
string = string + "bcd"; // Error: can't change string!
System.out.println(string);
}
}
One final note - another common cause of grief for new Java programmers when using Strings is that String has methods that appear to mutate the string but in actuality do not. For example, this code does not work correctly:
String s = "HELLO, WORLD!";
s.toLowerCase(); // Legal but incorrect
System.out.println(s); // Prints HELLO, WORLD!
Here, the call to s.toLowerCase() does not actually convert the characters of the string to lower case, but instead produces a new string with the characters set to lower case. If you then rewrite the code as
String s = "HELLO, WORLD!";
s = s.toLowerCase(); // Legal and correct
System.out.println(s); // Prints hello, world!
Then the code will behave properly. Again, the key detail here is that the assignment to s does not change any concrete String object, but just adjusts what object s refers to.
Hope this helps!
Nope, no error - you're not changing the contents of any string object.
You're changing the value of a string variable which is entirely different. Look at this as two operations:
Creating a new string, the result of the expression string + "bcd"
Assigning the reference to the new string back to the string variable
Let's separate them out explicitly:
String string = "abc";
String other = string + "bcd";
// abc - neither the value of string nor the object's contents have changed
System.out.println(string);
// This is *just* changing the value of the string variable. It's not making
// any changes to the data within any objects.
string = other;
It's very important to distinguish between variables and objects. The value of a variable is only ever a reference or a primitive type value. Changing the value of a variable does not change the contents of the object to which it previously referred.
The difference is between References to an object and the object itself.
String XXX = "xxx";
Means:
Make a new variable and assign the reference to an instance of object String that contains the literal string "xxx".
XXX = XXX + "yyy";
Means:
Get the reference to the object we have in variable named XXX.
Make a new object of type String that contains the string literal "yyy".
Add them together executing the string + operator.
This operation will create a new String object that contains the literal string "xxxyyy".
After all this, we put the reference to the new object again in the variable XXX.
The old referenced object containing "xxx" is not used anymore but the content of it was never modified.
As a counter proof, there is an example:
String a = "abc";
String b = "def";
String c = a;
a = a + b;
System.out.println(a); // will print "abcdef".
System.out.println(b); // will print "def".
System.out.println(c); // will print "abc".
// Now we compare references, in java == operator compare references, not the content of objects.
System.out.println(a == a); // Will print true
System.out.println(a == c); // Will print false, objects are not the same!
a = c;
System.out.println(a == c); // Will print true, now a and b points on the same instance.
Object instance are something "abstract" that live in a portion of memory of your program. A reference variable is a reference to that portion of memory.
You can access objects only through variables (or return values).
A single object can have more than one variable pointing at it.
String is immutable means that you cannot modify the content of that area of memory used by the String object, but of course, you are free to change and exchange references to it as you prefer.
It doesn't refute it. It actually won't compile since string isn't declared as a String object. But, let's say you meant:
class toString{
public static void main(String[] args){
String string = "abc";
string = string + "bcd";
System.out.println(string);
}
}
See the + operator creates a new String leaving "abc" in tact. The original "abc" still exists, but all you've actually done is create a new string "abcbcd" and overwrite the original reference to "abc" when doing: string = string + "bcd". If you changed that code to this you'll see what I mean:
class toString {
public static void main(String[] args ) {
String originalString = "abc";
String newString = originalString + "bcd";
System.out.println( originalString ); // prints the original "abc";
System.out.println( newString ); // prints the new string "abcbcd";
}
}
String objects are immutable, you are simply re-assigning the value of string to string + "bcd" in your code example. You are not modifying the existing String object, you are creating a new one and assigning it to the old name.
string = string + "bcd" sets a new instance of String to the variable string, rather than modify that object
what this will do is that it will make a new object, and replace the old one.
if you want mutable string look at string builder.
The String variable string itself is mutable.
The String object "abc" is immutable, as is the String object "bcd", and the result of the concatenation, "abcbcd". That last result is assigned to the variable.
No String was mutated in the execution of that code snipped.
The string is immutable... all your example does is show that you can assign a new string reference to a variable.
If we make the code compile, and change it slightly:
class toString{
public static void main(String[] args){
String string = "abc";
System.out.println(string);
string = string + "bcd";
System.out.println(string);
}
}
You will see "abc" and then "abcbcd" which, could lead you to think that the string has changed, but it has not.
When you do the string = /* whatever */ you are overwriting what used to be in the variable called string with a new value.
If String had a method, such as setCharAt(int index, char value) then it would be mutable.

Categories

Resources