Strings - How do they work? - java

How do String objects work in Java? How does term "immutable" exactly apply to string objects? Why don't we see modified string after passing through some method, though we operate on original string object value?

a String has a private final char[] . when a new String object is created, the array is also created and filled. it cannot be later accessed [from outside] or modified [actually it can be done with reflection, but we'll leave this aside].
it is "immutable" because once a string is created, its value cannot be changed, a "cow" string will always have the value "cow".
We don't see modified string because it is immutable, the same object will never be changed, no matter what you do with it [besides modifying it with reflection]. so "cow" + " horse" will create a new String object, and NOT modify the last object.
if you define:
void foo(String arg) {
arg= arg + " horse";
}
and you call:
String str = "cow";
foo(str);
the str where the call is is not modified [since it is the original reference to the same object!] when you changed arg, you simply changed it to reference another String object, and did NOT change the actual original object. so str, will be the same object, which was not changed, still containing "cow"
if you still want to change a String object, you can do it with reflection. However, it is unadvised and can have some serious side-affects:
String str = "cow";
try {
Field value = str.getClass().getDeclaredField("value");
Field count = str.getClass().getDeclaredField("count");
Field hash = str.getClass().getDeclaredField("hash");
Field offset = str.getClass().getDeclaredField("offset");
value.setAccessible(true);
count.setAccessible(true);
hash.setAccessible(true);
offset.setAccessible(true);
char[] newVal = { 'c','o','w',' ','h','o','r','s','e' };
value.set(str,newVal);
count.set(str,newVal.length);
hash.set(str,0);
offset.set(str,0);
} catch (NoSuchFieldException e) {
} catch (IllegalAccessException e) {}
System.out.println(str);
}

From the tutorial:
The String class is immutable, so that once it is created a String object cannot be changed. The String class has a number of methods, some of which will be discussed below, that appear to modify strings. Since strings are immutable, what these methods really do is create and return a new string that contains the result of the operation.

Strings in Java are immutable (state cannot be modified once created). This offers opportunities for optimization. One example is string interning, where string literals are maintained in a string pool and new String objects are only created if the particular string literal doesn't already exist in the pool. If the string literal already exists, a reference is returned. This can only be accomplished because strings are immutable, so you don't have to worry that some object holding a reference will change it.
Methods that appear to modify a string actually return a new instance. One example is string concatenation:
String s = "";
for( int i = 0; i < 5; i++ ){
s = s + "hi";
}
What actually happens internally (the compiler changes it):
String s = "";
for( int i = 0; i < 5; i++ ){
StringBuffer sb = new StringBuffer();
sb.append(s);
sb.append("hi");
s = sb.toString();
}
You can clearly see that new instances are created by the toString method (note that this can be made more efficient by directly using StringBuffers). StringBuffers are mutable, unlike Strings.

Every object has state. The state of a String object is the array of characters that make up the String, for example, the String "foo" contains the array ['f', 'o', 'o']. Because a String is immutable, this array can never be changed in any way, shape, or form.
Every method in every class that wants to change a String must instead return a new String that represents the altered state of the old String. That is, if you try to reverse "foo" you will get a new String object with internal state ['o', 'o', 'f'].

I think this link will help you to understand how Java String really works
Now consider the following code -
String s = "ABC";
s.toLowerCase();
The method toLowerCase() will not change the data "ABC" that s contains. Instead, a new String object is instantiated and given the data "abc" during its construction. A reference to this String object is returned by the toLowerCase() method. To make the String s contain the data "abc", a different approach is needed.
Again consider the following - s = s.toLowerCase();
Now the String s references a new String object that contains "abc". There is nothing in the syntax of the declaration of the class String that enforces it as immutable; rather, none of the String class's methods ever affect the data that a String object contains, thus making it immutable.
I don't really understood your third question. May be providing a chunk of code and telling your problem is a better option. Hope this helps.
You can also look into this blogpost for more understanding
[code samples are taken from the wiki. you can also look in there for more information]

Related

What is the difference between String initializations by new String() and new String("") in Java?

What is the difference between the following two initializations in Java?
String a = new String();
String b = new String("");
Well, they are almost the same.
public static void main(String[] args) {
String s1 = new String();
String s2 = new String("");
System.out.println(s1.equals(s2)); // returns true.
}
Minor differences (rather insignificant) :
new String(); takes less time to execute than new String(""); because the copy constructor does a lot of stuff.
new String("") adds the empty String ("") to the String constants pool if it is not already present.
Other than this, there are no other differences
Note : The use of new String("abc") is almost always bad because you will be creating 2 Strings one on String constants pool and another on heap with the same value.
Java Docs explains it beautifully
These are 2 different constructor calling
public String()
Initializes a newly created String object so that it represents an
empty character sequence. Note that use of this constructor is
unnecessary since Strings are immutable.
public String(String original)
Initializes a newly created String object so that it represents the
same sequence of characters as the argument; in other words, the newly
created string is a copy of the argument string. Unless an explicit
copy of original is needed, use of this constructor is unnecessary
since Strings are immutable.
Internally, different constructors will be invoked.
However, the resulting String objects will be identical by their content and equal (a.equals(b) will return true)
TheLostMind is mostly correct, but I'd like to add that the copy constructor doesn't actually do that much:
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/lang/String.java#137
137 public String() {138 this.value = new char[0];139 }151 public String(String original) {152 this.value = original.value;153 this.hash = original.hash;154 }
Using the constant "" will use the first constructor to create the object reference anyway, so it doesn't matter too much which one you use.
In any case, I would recommend using the string literal "" because you can save an object reference if you use that string elsewhere. Only use the String constructor if you really need a copy of that string that isn't used anywhere else.
In first case you create only one String object in second case two: "" and new String, if "" object not already exist in string pool.
Initializes a newly created String object so that it represents an
empty character sequence.
Initializes a newly created String object so that it represents the
same sequence of characters as the argument; in other words, the newly
created string is a copy of the argument string.
The first is calling the default constructor and the second is calling the copy constructor in order to create a new string in each case.
From a purely practical point of view, there is zero difference between those constructions, as there is never any reason to ever use either of them. They are both wasteful and over-complicated, and thus equally pointless.
To initialize a variable with the empty string, do:
String s = "";
That is shorter and plainer to type, and avoids creating any String objects, since the one shared "" instance in the intern pool will certainly have already been loaded by some other class anyway.

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.

Are Strings also static: String creation within Methods

I know that at compile time when a String is created, that String will be THE string used by any objects of that particular signature.
String s = "foo"; <--Any other identical strings will simply be references to this object.
Does this hold for strings created during methods at runtime? I have some code where an object holds a piece of string data. The original code is something like
for(datum :data){
String a = datum.getD(); //getD is not doing anything but returning a field
StringBuffer toAppend = new StringBuffer(a).append(stuff).toString();
someData = someObject.getMethod(a);
//do stuff
}
Since the String was already created in data, it seems better to just call datum.getD() instead of creating a string on every iteration of the loop.
Unless there's something I'm missing?
String instances are shared when they are the result of a compile-time constant expression. As a result, in the example below a and c will point to the same instance, but b will be a different instance, even though they all represent the same value:
String a = "hello";
String b = hell() + o();
String c = "hell" + "o";
public String hell() {
return "hell";
}
public String o() {
return "o";
}
You can explicitly intern the String however:
String b = (hell() + o()).intern();
In which case they'll all point to the same object.
The line
String a = datum.getD();
means, assign the result of evaluating datum.getD() to the reference a . It doesn't create a new String.
You are correct that strings are immutable so all references to the same string value use the same object.
As far as being static, I do not think Strings are static in the way you describe. The Class class is like that, but I think it is the only object that does that.
I think it would be better to just call the datum.getD() since there is nothing that pulling it out into its own sting object gains for you.
If you do use the datum.getD() several times in the loop, then it might make sense to pull the value into a String object, because the cost of creating a string object once might be less than the cost of calling the getD() function multiple times.

Categories

Resources