Are Strings overwritable? - java

My textbook says a String is not over-writable or immutable, i.e, once you enter the value of a String you can't change it. But today when I was running the following code, the String str gets muted as the compiler does not give any error and the new String a's value is successfully entered into str.
class Test
{
static void main()
{
String str = "something";
String a ="anything";
str = a; //str is being over written without any error
System.out.println(str);
}
}
The output is : anything
So, is my book wrong ?
If my book is not wrong please give an example to show that Strings are immutable

The book is correct. When you say str = a you are not changing anything about the String 'something'. You should distinguish between str and something, they are not the same. "something" here is a String object in memory, whereas str is just the reference to that string. Same with the reference a.
When you say:
str = a
You are not changing something, you are in fact saying, "change the reference str to point to whatever the reference a is pointing to." The Strings remain the same, the references change.
On a similar note, this is why you may see in your book that concatenating Strings is expensive, as doing something like:
str = str + a
Would again not be changing the existing Strings, but instead creating a new String object which is equal to the concatenation of the String that the reference str is referring to and the String that the reference a is referring to.

You need to understand what immutable means. In your scenario you are just changing references.
str = a;
will make both a and str to point to String "anything". The Text Book is correct. String is immutable and can not be overwritten. If you check the JavaDoc for String. Most of the methods return a String. This is because any operation in a String will not change that String object but will result in a new String being created. Effectively you can never change a String after you create it. By Change I mean append new characters, remove characters without a new String object being created.

As many answers already point out is that you only change references. Immutable means you cannot change the string itself. for example you do:
String a = "anything";
System.out.println(a); // -> anything
a.substring(3);
System.out.println(a); // -> anything : this is because the String itself is
// immutable.
a = a.substring(3);
System.out.println(a); // -> thing : this is what immutable means to edit a string
// you must reassign it or assign it
// to a new variable

You're changing the reference of str to a. So str effectively becomes a's value.

they are just pointer to that string. so when you do str =a , you just assign pointer of a to str.

The contents of the String object is not being changed. What's happening is that a new String object is being assigned to the variable. The old String object still exists in memory but you just can't refer to it any more. The 'str' variable now refers to the String object containing "anything" but the String containing "something" still exists as it did before. Try assigning 'str' to another variable first and then, after assigning 'a' to 'str', check that other variable and you'll see that it still says "something", proving that that String was not overwritten.

In Java, the value of a variable is never an object, but a reference. Relevant to your case, the type String on the a variable says the variable is allowed to contain only references to String objects.
You can update the value in the variable, sure; but that won't touch the object it is referring to.

Strings are constant; their values cannot be changed after they are created.
The String object is created and stored on constant pool or literal pool.
In your case, when you say,
String str="something"; // An object is created on constant pool with value 'something' and reference 'str' is pointing to it.
String a="anything"; // An object is created on constant pool with value 'anything' and reference 'a' is pointing to it.
And when you do, str=a; then 'str' actually start pointed to 'a', but the object with value as 'something' remains on constant pool with the same value.

Related

String immutability - (concat and assigning a new value)

I have a question about String's immutability, namely, in the first situation the variable name does not change.
String name = "Unknown" ;
name.concat("Boy");
System.out.println (name);
But in the second case, the variable changes its value.
String name = "Unknown" ;
System.out.println (name);
name = "Test";
System.out.println(name);
Why the variable does not change in the first case, but in the second case as much as possible?
Strings are immutable - they do not change.
The name variable is pointing to the string "Unknown"
If you look at the docs for String found here,
you will see that concat() returns a String which is the brand new String that concatenates "Unknown" with "Boy".
The name variable is still pointing to the "Unknown" string.
In order for name to change you need to reassign it to the String returned by concat:
name = name.concat("Boy");
In the second example you're reassigning the reference to "Test".
None of the strings changed, just the references.
Thats how string concatnation works. It doesnt concat to your existing string, but creates a new one.
String name = "Unknown" ;
name.concat("Boy");
This creates and returns a new string "UnknownBoy" which you don't store.
Refer to the String API for how the method behaves. https://docs.oracle.com/javase/9/docs/api/java/lang/String.html#concat-java.lang.String-
It looks you are confused between the reference variable and Object, in your case name is a reference variable of type String which can hold the reference to a String object. Please go through this for the understanding of reference, variable and object.
In your first case, name is a variable which holds the reference to the String Object "Unkown" and when name.concat("Boy") a new String object ("UnkownBoy") will be created but name variable still holds the reference to the old object ("Unkown") because you did not update the reference anywhere in the first case.
In your second case you have updated the reference variable by name = "Test"; , that means now name will hold the reference of a new String Object "Test".

Java- creating a String object but assigning otherwise afterwards

I have a question concerning establishing String objects in Java.
Let's say I create a String object like this:
String mystring=new String();
Now, if I take this String object and assign to it a string like this:
mystring="abc";
What exactly happened here? Is mystring addressed exactly to the original object or is it a different object? Like String mystring; is the short-hand for String mystring=new String(); what could mystring="abc"; stand for?
String mystring = new String();
creates a new String object and assigns the value of its reference to the variable mystring.
So
Variable Heap
-------- ----
mytring ---------------------> "" // an empty String object
Then you do
mystring="abc";
This assigns the value of the reference to the String object "abc" to the variable mystring. So
Variable Heap
-------- ----
mystring -------------------> "abc"
"" // will be garbage collected at some point
A variable does not change. The object it's referencing or the reference itself can change.
Like String mystring; is the short-term for String mystring=new
String();
No String mystring; is a variable declaration. When that line is executed, the variable mystring is declared but not initialized.
On the other hand, String mystring = new String() both declares and initializes the variable mystring.
for what could mystring="abc"; stand for?
That is an assignment expression, assigning the value of the reference to the String object "abc" to the variable mystring.
It's also important to understand that Strings are immutable. Once you create a String object, you cannot change it. For example, in the following code
String name = "user3133542"; // cool
name = "some other value";
You are not changing the object that name is referencing, you are creating a new object and assigning its value to the variable name.
The String API does not provide any methods to change its value. We therefore call it immutable.
Consider going through the Java String tutorial.
Also, before you ask your next question, read this
How do I compare strings in Java?
You are changing mystring with mystring="abc"; It is not the exactly to the original object at all. The mystring is a variable not object.

How to access the object of String pool

Can we able to access the object in String pool which is does not not have any reference.
Here is code :
String str ="abc";
str.toUpperCase();
System.out.println(str); // System.out.println(str.toUpperCase());
Output : abc
Here I am performing the toUpperCase() operation on str. In String pool one object will be created for this str.toUpperCase();. Can we able to access this object.? if yes how?
This is where java documentation is used .... Refer http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#toUpperCase()
str.toUpperCase() returns a string converted to upper case, you have to assign it to another string variable or do a self assignment, so you can access it later.
String str ="abc"; // 1
str.toUpperCase(); // 2
System.out.println(str); // 3
in above code
First line will create new Object of String with value "abc" and assign it to the reference variable str.
Second line will create the new Object of String because String class is immutable so original Object str will not change. but here we are not assigning the new object which is created in line 2 so it will be lost somewhere in Heap area.
That is why in line 3 printing value is "abc".
if you want to use the new Object created by str.toUpperCase() than have to assign that in a new reference variable.
or
alternative option is update the original String Object like this
str = str.toUpperCase();
but in above operation, the original Object str containing the value "abc" will be lost in the Heap area !!!!!
You can find details about working with String by example here.

How do Java strings work [duplicate]

This question already has answers here:
What is meant by immutable?
(17 answers)
Closed 9 years ago.
I'm trying to understand exactly how Java strings are immutable. I get that this should probably be an easy concept, but after reading several online web pages I still don't quite understand.
I don't understand how Java Strings are "immutable". I currently have the following code:
public static void main(String[] args) {
String name = "Jacob Perkins";
System.out.println( name );
name = name + "!";
System.out.println( name );
}
My output is the following:
Jacob Perkins
Jacob Perkins!
Why is this happening if a string is supposed to be immutable? Why am I able to re-assign a value to the string?
Let an image explain this for you:
On the left side, you have the variable, which in fact is a reference.
String name = "Jacob Perkins;" The String "Jacob Perkins" is created, and name points to it.
name = name + "!"; A new String "Jakob Perkins!" is created, and the reference now points to the new String. The old one, however, remains unchanged, because String is immutable.
The string itself, once created, can never be changed. What your code sample does is to replace the string in name with a new string that was constructed from the previous contents of name, and an exclamation point. (The original contents of name, which are no longer referenced by any variable, will eventually be reaped by the garbage collector.)
If you were to examine the compiled code (or step through it with a debugger), you would discover that your name + "!" expression had been compiled into the creation of a StringBuilder object and a few operations on that object.
That is, the strings are immutable, but the variable name is not. Its value changes, to point to different strings. The strings themselves never change.
The String objects are immutable only the variable reference changes.
In your example the "Jacob Perkins" object still exists and a new object "Jacob Perkins!" gets created.
The name variable points to the new object.
Maybe this will help you to understand.
Let's say you have a class Point (java.awt.Point).
Let's say you have one instance p:
Point p = new Point(0,0);
Then you make create a new variable y referencing the same object p as:
Point y = p;
If you change the value of p, you also change y. Because the class Point is mutable.
p.setLocation(1,1);
It makes y reference the location 1,1 as well.
Using the String class it does not happen.
String a = "123";
String b = a;
If you make a = a + "4";
The new value of a will be "1234" but b is still "123";
The object they were referencing didn't change, it's just that a is pointing to another object now.
What actually happens is there are 3 String objects created. "Jacob Perkins", "!" and "Jacob Perkins!". You didn't really modify the "Jacob Perkins" instance. You just changed the reference of the name variable, from "Jacob Perkins" instance to "Jacob Perkins!".
String name = "Jacob Perkins";
String name2 = name + "!";
name.substring(5); // or wather syntax is
Those do not change variable name
In Java there are references and there are values.
When you say
String foo = "John Smith";
foo is a variable, holding a reference. The reference points to the object, or value, containing "John Smith".
The reference held by the variable is mutable. I can do this:
foo = "Jack Smith";
And I have mutated the reference. However if I write code like this:
String foo = "John Smith";
String bar = foo; //bar's reference is a copy of foo's reference - the same value
foo = "Jack Smith";
System.out.println(bar); //prints John Smith
We see that even though we changed foo, bar has not changed. Why? Simply, when we wrote foo = "Jack Smith"; we made foo point to a new String. We didn't reach through foo and modify the string, since No method in Java mutates, or can mutate a String. Instead, a new String is returned, and the variable is made to point to the new, also immutable String. This way, the object a String variable 'points' to can never be modified by anything but through that variable. This is an important property of the Java language that it guarantees.

Does it make a copy before adding Strings into a Collection?

List<String> list = new ArrayList<String>();
String string = null;
string = "123";
list.add(string);
string = "456";
list.add(string);
for (String s : list)
{
System.out.println(s);
}
This program outputs:
123
456
which is pretty natural.
However, I'm thinking in another way. "string" is the reference(pointer) to the actual String object. When executing add(), it just stores the reference. When "string" refers to another String object, why the list still keeps the original one? Does it make a copy before add()?
The "value" of a String variable is a reference to the (immutable) object that is the string.
So there is no copy of the String but a copy of the reference. Having this reference doesn't allow you to change the original variable (you have no link to it) and doesn't allow you to change the string as it is immutable.
What you have here, inside the array contained by the arrayList after the two calls to add, is two different references. They could point to the same string but changing one reference doesn't change the other one. If you wanted to change the first reference in this case to point to the same string as the second one, the simplest would have been to do list.set(0, list.get(1));
When "string" refers to another String object, why the list still keeps the original one?
What you've added to the list is the reference to the string. Later, when you do
string = "456";
you're not changing the existing string, you're assigning a reference to a different string to the string variable. The original string is unchanged (in fact, strings in Java are immutable).
because the variable 'string' is nothing but a pointer to a address in the memory. when you add 'string' in list the memory address of the 'string' is entered in the list. when you again assign a value , it justs change the address in the memory where the new variable is pointing

Categories