So I know there are other similar questions to this, such as this one and this other one. But Their answer seems to be that because they are literal and part of some pool of immutable literal constants, they will remain available. This sort of makes sense to me, but then why do non literals also work fine? When do I ever have to use the "new" keyword when dealing with strings. In the example below, I use strings to do a few things, but everything works fine and I never use the "new" keyword (correction: I never use it with a String type object).
import java.util.*;
class teststrings{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
String nonew;
String nonew2;
String literally= "old";
literally= "new"; //does the word "old" get garbage collected here?
nonew = in.nextLine(); //this does not use the new keyword, but it works, why?
System.out.println("nonew:"+nonew);
System.out.println("literally:"+literally);
nonew2 = in.nextLine();
System.out.println("nonew:"+nonew); //the data is still preserved here
System.out.println("nonew2:"+nonew2);
//I didn't use the new keyword at all, but everything worked
//So, when do I need to use it?
}
}
A couple of points:
"Does the word "old" get garbage collected here?"
Chances are your compiler realises it's never used and just skips it altogether.
Scanner::nextLine returns a String, and the value returned by the method is used for the assignment.
As for when to use new for Strings... Well, rarely would probably be best. The only time I've ever seen it used would be for internal constants. For example
public class MatchChecker {
private static final String ANY_VALUE = new String("*");
private final Map<Object, String> map = new HashMap<Object, String>();
public void addMatch(Object object, String string) {
map.put(object, string);
}
public void addAnyValueMatch(Object object) {
map.put(object, ANY_VALUE);
}
public boolean matches(Object object, String string) {
if (!map.contains(object)) {
return false;
}
if (map.get(object) == ANY_VALUE || map.get(object).equals(string)) {
return true;
}
return false;
}
}
Which would mean only those Objects added via addAnyValueMatch would match any value (as it's tested with ==), even if the user used "*" as the string in addMatch.
Strings are treated specially in Java. The Java JVM makes use of a cache like implementation called a String pool.
Unlike other objects, when you create a literal String like this: String mystring = "Hello"; Java will first check to see if the String "Hello" already exists in the String pool. If not, it will add it to be cached and reused if referenced again.
So, when you assign a variable to "Hello" the first time, it gets added to the pool:
String s1 = "Hello";
String s2 = "Hello";
String s3 = s1;
s1 = "SomethingElse"
In the code above, when s1 is assigned "Hello" the JVM will see it is not stored in the pool and create/add it to the pool.
For s2, you are again referencing "Hello". The JVM will see it in the pool and assign s2 to the same String stored in the pool. s3 is simply assigned to the value referenced at the memory address of s1, or the same string "Hello". Finally, s1 is then reassigned to another String, which doesn't exist yet in the pool, so is added. Also, s1 no longer points to "Hello", yet it will not be garbage collected, for two reasons. 1:t is being stored in the String pool and 2: s2 also points to the same referenced string.
With Strings, you should never use the new keyword for creating literal strings. If you do, you are not taking advantage of the String pool reuse and could cause multiple instances of the same String to exist in memory, which is a waste.
Related
I know there are two ways of creating String in Java:
String a = "aaa";
String b = new String("bbb");
With the first way Java will definitely create a String object in the string pool and make a refer to it. (Assume "aaa" wan't in the pool before.)
With the second method, an object will be created in the heap, but will jvm also create an object in the string pool?
In this post Questions about Java's String pool, #Jesper said:
If you do this:
String s = new String("abc");
then there will be one String object in the pool, the one that represents the literal "abc", > and there will be a separate String object, not in the pool, that contains a copy of the > content of the pooled object.
If that's true, then every time with the new String("bbb");, a object "bbb" is created in the pool, which means by either way above, java will always create a string object in the pool. Then what is intern() used for ? In the docs http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern(), it says:
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
That means there are cases that a string is not in the pool, is that possible ? Which one is true ?
As you know that String is an immutable object in Java programming language, which means once constructed can not be altered. Due to this, JVM has the ability to maintain a literal pool which is helpful to reduce the memory usage and to increase the performance. Each time when a String literal is used JVM checks the literal pool. If the literal is already available, the same reference would be returned. If the literal is not available, a new String object will be created and added in the literal pool.
This theory is applied when you try to create a String like a primitive or a literal/constant.
String str = "bbb";
But when you create a new String object
String str = new String("bbb");
the above mentioned rules are overridden and a new instance is created always.
But the intern API in the String class can be used to pick the String reference from the literal pool even though you create a String using new operator. Please check the below given example. Although the str3 is created using new operator since we used the intern method JVM picked up the reference from the literal pool.
public class StringInternExample {
public static void main(final String args[]) {
final String str = "bbb";
final String str1 = "bbb";
final String str2 = new String("bbb");
final String str3 = new String("bbb").intern();
System.out.println("str == str1 : "+(str == str1));
System.out.println("str == str2 : "+(str == str2));
System.out.println("str == str3 : "+(str == str3));
}
}
Output of above code:
str == str1 : true
str == str2 : false
str == str3 : true
You can have a look: Confusion on string immutability
Source of answer: http://ourownjava.com/java/java-string-immutability-and-intern-method/
Shishir
There are essentially two ways that our String objects can enter in to the pool:
Using a literal in source code like "bbb".
Using intern.
intern is for when you have a String that's not otherwise from the pool. For example:
String bb = "bbb".substring(1); // substring creates a new object
System.out.println(bb == "bb"); // false
System.out.println(bb.intern() == "bb"); // true
Or slightly different:
System.out.println(new String("bbb").intern() == "bbb"); // true
new String("bbb") does create two objects...
String fromLiteral = "bbb"; // in pool
String fromNewString = new String(fromLiteral); // not in pool
...but it's more like a special case. It creates two objects because "bbb" refers to an object:
A string literal is a reference to an instance of class String [...].
Moreover, a string literal always refers to the same instance of class String.
And new String(...) creates a copy of it.
However, there are many ways String objects are created without using a literal, such as:
All the String methods that perform some kind of mutation. (substring, split, replace, etc.)
Reading a String from some kind of input such as a Scanner or Reader.
Concatenation when at least one operand is not a compile-time constant.
intern lets you add them to the pool or retrieve an existing object if there was one. Under most circumstances interning Strings is unnecessary but it can be used as an optimization because:
It lets you compare with ==.
It can save memory because duplicates can be garbage collected.
Yes, new String("abc") will create a new object in memory, and thus it is advised to avoid it. Please have a look at item 5 of Josh Bloch's Effective Java, "Avoid creating unnecessary objects" where it is better explained:
As an extreme example of what not to do, consider this statement:
String s = new String("stringette"); // DON'T DO THIS!
The statement
creates a new String instance each time it is executed, and none of
those object creations is necessary. The argument to the String
constructor ("stringette") is itself a String instance, functionally
identical to all of the objects created by the constructor. If this
usage occurs in a loop or in a frequently invoked method, millions of
String instances can be created needlessly. The improved version is
simply the following:
String s = "stringette";
This version uses a
single String instance, rather than creating a new one each time it is
executed. Furthermore, it is guaranteed that the object will be reused
by any other code running in the same virtual machine that happens to
contain the same string literal [JLS, 3.10.5].
http://uet.vnu.edu.vn/~chauttm/e-books/java/Effective.Java.2nd.Edition.May.2008.3000th.Release.pdf
With the second method, an object will be created in the heap, but will jvm also create an object in the string pool?
Yes, but it is the string literal "bbb" which ensures the interned string1. The string constructor creates a new string object which is a copy with the same length and content - the newly created string is not automatically interned.
If that's true, then every time with the new String("bbb");, a object "bbb" is created in the pool, which means by either way above, java will always create a string object in the pool. Then what is intern() used for ?
Only string literals are automatically interned. Other string objects must be manually interned, if such is the desired behavior.
That means there are cases that a string is not in the pool, is that possible ?
With the exception of manual calls to String.intern, only string literals result in interned strings.
While I would recommend using a specialized collection for such cases, interning may be useful where it can be used to avoid creating extra duplicate objects. Some use-cases where interning can be beneficial - as in, the same string value can appear many times - is in JSON keys and XML element/attribute names.
1 This is trivial to reason, consider:
String _b = "bbb"; // string from string literal (this is interned)
String b = new String(_b); // create a NEW string via "copy constructor"
b == _b // -> false (new did NOT return an interned string)
b.equals(_b) // -> true (but it did return an equivalent string)
b.intern() == _b // -> true (which interns to .. the same string object)
Excuse me if this question is already asked or if its very old.
String is a Class. We are able to assign the value to String without creating new instance object.
like String someString = "Value";
How this is working without creating instance for String? Is it possible to create user defined class to assign values directly without creating new object?
See this interesting article:
String is Really Special
The designers of Java decided to retain primitive types in an
object-oriented language, instead of making everything an object, so
as to improve the performance of the language. Primitives are stored
in the call stack, which require less storage spaces and are cheaper
to manipulate. On the other hand, objects are stored in the program
heap, which require complex memory management and more storage spaces.
For performance reason, Java's String is designed to be in between a
primitive and a class.
Also:
Java has provided a special mechanism for keeping the String literals
- in a so-called string common pool..
When you do:
String myStr1 = "Hello";
String myStr2 = "Hello";
Then
myStr1 == myStr2 is true, because they're both stored in the pool (Read the article).
But if you construct a new String object:
String myStr1 = new String("Hello");
String myStr2 = new String("Hello");
Then the references are not equal.
I highly recommend to visit the JLS. It says that Strings are treated in a different way, just like that :)
String str = "abc";
is equivalent to:
char data[] = {'a', 'b', 'c'};
or
String str = new String(data);
For user defined classes, you have to create an object.
Refer to docs please for more information:
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html
Strings are a special case. The String literals are created in the string pool. After a string is added in the pool, if another with the same value will be declared, the reference will point to the same string in the pool.
And to answer your question, you cannot create user defined classes and not use new. Only if you use only static methods and fields on that class and then you use
ClassName.StaticFieldOrMethod.
To know more about how String class works refer
http://java.dzone.com/articles/string-memory-internals
Let us try to understand this with a simple program;
package program;
public class TempList {
public static void main(String[] args) throws Exception {
String stringWithoutNew = "Test";
String stringWithoutNew_temp = "Test";
String stringWithNew = new String("Test");
String stringWithNew_temp = new String("Test");
if (stringWithoutNew == stringWithoutNew_temp) {
System.out.println("This works !!");
}
if (stringWithoutNew == stringWithNew) {
System.out.println("This doesn't work !!");
}
if (stringWithNew == stringWithNew_temp) {
System.out.println("This doesn't work either !!");
}
}
}
I am not able to figure out that if
String ab = "hello"; //straight initialization
String ab_1 = new String ("hello_1"); //initializing using new
both work, but
StringBuffer bfr = new StringBuffer("hi"); //works only with new
works only if created with new.
Why it is that String can be instantiated directly but StringBuffer needs new operator. Can someone explain me the main reason please.
All objects need to be instantiated with new. Only primitives can be instantiated from a literal (int i = 0;).
The only exceptions are:
strings, which allow a special initialisation construct:
String s = "abc"; //can be instantiated from a literal, like primitives
null instantiation: Object o = null;
It is defined in the Java Language Specification #3.10:
A literal is the source code representation of a value of a primitive type, the String type, or the null type.
Note: arrays also have a dedicated initialisation patterm , but that's not a literal:
int[][] a = { { 00, 01 }, { 10, 11 } };
Using String s1 = "hello"; and String s2 = new String("hello"); have a subtle difference.
public static void main(String[] arg ) {
String s1 = "Java";
String s2 = "Java";
String s3 = new String("Java");
System.out.println(s1==s2); //true
System.out.println(s1==s3); //false
StringBuilder sb = new StringBuilder(25); //initial capacikacity
sb = new StringBuilder(10);
sb.append(s1).append(" uses immutable strings.");
sb.setCharAt(20, 'S');
System.out.println(sb);
}
In the above code, "Java" is known as a String literal. In order to save memory, both times this appears in the code, it is the same String literal, so s1 and s2 actually refer to the same object in memory. While s1.equals(s3) would be true, they do not reference the same object in memory as shown above.
In practice, we always use .equals to compare Strings and they are immutable, so we cannot change the data s1 refers to (at least not easily). But if we were able to change the data referenced by s1, then s2 would change along with it.
StringBuilder does let you modify the underlying data: we often use it to append one String to another as illustrated above. We can be glad that StringBuilder sb2 = "what?" is illegal because in the case of StringBuilders, having two of them reference the same data (meaning sb1==sb2) is more likely to lead to problems where a change in sb1 causes an unexpected change in sb2.
String ab = "hello"; //straight initialization
String ac = "hello"; // create one more reference ac
String is a special case when you use the new keyword, a new String object will be created. Note that objects are always on the heap - the string pool is not a separate memory area that is separate from the heap.The string pool is like a cache.
It is like this because Strings are something heavily used by java and creating String objects using new key word is expensive also that's why java has introduced StringPool concept.
If you declare one variable ac with same value , java will not create new object(String) it will simply refer to the same object(hello) which is already there in pool.
String ab_1 = new String ("hello_1"); //initializing using new
It will simple create object in memory and ab_1 will refer to that object.
Strings are quite a special case in Java (this is not really a good thing in my opinion, but that doesn't matter).
Strings, unlike other objects, can be instantiated directly like they were constants.
When you do this, the String constant is added to the String constant pool, and handled like it was a primitive. Let me give an example.
String a = "abc";
String b = "abc";
When you instantiate a as a "primitive" string, it gets added to the pool, when you instantiate b, the same object is returned from the pool, so if you do this:
a == b;
You'll get... true, since it's actually the same object. If you instantiate both with new, you'll get false, since you're comparing the references of two different Objects (new forces the creation of a distinct object).
Strings are handle specially by java compiler. When you type a string literal such as "hello", the compiler creates a new String object for you internally.
No such thing is performed for StringBuffers (although Java uses StringBuffers internally for another purpose - for implementing string concatenation).
See Difference between string object and string literal for more details.
Other pointers:
String, StringBuffer, and StringBuilder
+ operator for String in Java
There is also one more difference based on 'where' strings are 'stored' - memory or string constant pool.
To make Java more memory efficient, the JVM sets aside a special area
of memory called the "String constant pool." When the compiler
encounters a String literal, it checks the pool to see if an identical
String already exists. If a match is found, the reference to the new
literal is directed to the existing String, and no new String literal
object is created. (The existing String simply has an additional
reference.)
String s = "abc"; // creates one String object and one reference variable
In this simple case, "abc" will go in the pool and s will refer to it.
String s = new String("abc"); // creates two objects, and one reference variable
In this case, because we used the new keyword, Java will create a new String object
in normal (nonpool) memory, and s will refer to it. In addition, the literal "abc" will
be placed in the pool.
String is a mutable class and has in-build constructors which can create String object from the string literal.
There is no exception in case of String also (like creating it like primitive .e.g int i =0). String also executes constructor to initialize following (just difference is its abstract and not directly visible) :
String str = "ABC";
Becuase here "ABC" also represent one String object which can not be used directly by programmer but it resides in the String pool. And when this statement will be executed JVM will internally call the private constructor to create object using the "ABC" object which resides in the pool.
Basically, since Strings are used so much, Java offers a shorthand solution to instantiating a String.
Instead of always using this,
String str = new String ("hello");
Java makes it able to do this:
String str = "hello";
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.
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.