I understand that a String variable in Java is immutable and can therefore not be changed.
String myString = "Hello.";
myString += " ";
myString += "My name is Kevin";
Each time we "add" something to this String(), we are effectively creating a new String(), but this has the same name as the string it is being concatenated with. Does this mean there are multiple references in memory with the variable "myString"?
Each time you "modify"/concatenate the String with +=, you're creating a new String object and replacing the reference named myString with the newly-created String. So no, there is only one reference in memory, but the object the reference points to changes each time. The string is immutable, so the object cannot be modified "in place".
String is an immutable class in Java. An immutable class is simply a class whose instances cannot be modified. All information in an instance is initialized when the instance is created and the information can not be modified. There are many advantages of immutable classes.
There is a great answer on the Programmer's StackExchange explaining why Strings are immutable in Java, and more details about how exactly this works.
The best way to do this is to just use the StringBuilder() class:
String myStringBuilder = new StringBuilder("Hello.");
myStringBuilder.append(" ");
myStringBuilder.append("My name is Kevin");
System.out.println(myStringBuilder.toString());
However, String concatenation is translated into StringBuilder operations automatically by modern Java compilers.
No , you can not access to previous reference and it's left for garbage collector to collect it. in other words there is only one reference in memory which holds the current value of variable("My Name is Kevin)
note that if you r gonna change a String variable a lot , you should use StringBuilder class.
here is link to Documentation of StringBuilder class
you also can find lots example for using this class on internet
https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html
also here is detailed answer of your question
When will a string be garbage collected in java
String myString = "Hello.";
The above create a new Object and put "Hello." into memory which myString is reference to the Object.
myString += " ";
Here you can look as myString = myString + " "; a " " String is created and put into memory and the concatenation will result to create a new String which is referenced by myString.
Note that String concatenation with "+" has a O(N2) complexity while StringBuilder has O(N) in complexity. It is becase new String is created for the concatenation result every time while StringBuilder instead contains a sequence of characters. Therefore String concatenation is less efficient than using a StringBuilder especially need to build up a large amount of String.
Java uses a string pool. This is an implementation of the concept of string interning.
In computer science, string interning is a method of storing only one copy of each distinct string value, which must be immutable. Interning strings makes some string processing tasks more time- or space-efficient at the cost of requiring more time when the string is created or interned. The distinct values are stored in a string intern pool.
This means that for every string, a copy of that particular string is added to the string pool. Every variable that holds that exact string, points to that copy in the string pool.
The strings Hello., , and My name is Kevin are added to the string pool, since they're literals in the program.
String myString = "Hello.";
The variable myString starts pointing to the string Hello., which is already in the string pool.
myString += " ";
The string Hello. (note the extra space at the end) is added to the pool. The variable myString now points to that.
myString += "My name is Kevin";
The string Hello. My name is Kevin is added to the pool. The variable myString now points to that.
Strings in the pool that are no longer being referenced by variables, are eligible for garbage collection, so Hello. (with the space at the end), can now be garbage collected.
here your Code in which you define a String reference variable myString.
String is a immutable class, it means there is no modification can be made in object once it created.
Here "Hello" creates a String Object and refer the object by myString.
String myString = "Hello."; //create a Object String contain Hello and refer to myString
myString += " ";
myString += "My name is Kevin";
when myString+=" "; getting executed it creates another new object of String by concaticate "Hello" in it.
"Hello " a new Object created and myString refers to it. "Hello" is eligible for garbage Collection.
again when myString += "My name is Kevin"; getting executed, it creates another new Object of String by concatinate "Hello " in it.
Your new Object "Hello My Name is Kevin" is referred by myString reference Variable of String Type.
Now, Your both earlier Objects "Hello" and "Hello/s" is not referenced by any other reference variable, So, It is eligible for garbage Collection.
Thanks
Related
In Java when we use literal string when creating a string object, I know that a new object is created in SCP (string constant pool).
Is there a way to check if a variable is in the SCP or in the heap?
First of all, the correct term is the "string pool", not the "string constant pool"; see String pool - do String always exist in constant pool?
Secondly, you are not checking a variable. You are checking the string that some variable contains / refers to. (A variable that contains a reference to the string, cannot be be "in the SCP". The variable is either on the stack, in the heap (not SCP), or in metaspace.)
Is there a way to check if a variable is in SCP or in heap ?
From Java 7 and later, the string pool is in the (normal) heap. So your question is moot if we interpret it literally.
Prior to Java 7, the way to check if a String is in the string pool was to do this
if (str == str.intern()) {
System.out.println("In the string pool");
}
However, this had the problem that if an equivalent str was not already in the pool, you would have added a copy of str to the pool.
From Java 7 onwards, the above test is no longer reliable. A str.intern() no longer needs to copy a string to a separate region to add it the string pool. Therefore the reference to an intern'd string is often identical to the reference to the original (non-interned) string.
char[] chars = new char[]{'a', 'b', 'c'};
String str = new String(chars);
String interned = str.intern();
System.out.println(str == interned);
In fact str == str.intern() can only detect the case where you have a non-interned string with the same content as a string literal.
Or at least list all string instances in SCP ?
There is no way to do that.
As JB Nizet pointed out, there is really not a lot of point in asking these questions:
You shouldn't be writing code that depends on whether a string is in the string pool or not.
If you are concerned about storage to the level where you would contemplate calling intern for yourself, it is better to make use of the opportunistic string compaction mechanism provided by Java 9+ garbage collectors.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I was looking into the String API and suddenly I came across one String empty Constructor i.e. we can construct an empty String object using String s = new String()
I wonder is there any use of it?
Ofcourse.....
String s = new String();
will create a Non-literal String object on the heap, which will be garbage collected.
where as
String s = "" ;
will create a String Literal. This will not be garbage collected ever, if it is reachable through the default loader.
See this link below to a question which I asked. This may not be directly related to your question, but it will certainly help you grasp the concept firmly.
Is String Literal Pool a collection of references to the String Object, Or a collection of Objects
It creates the empty string, which appears to have some limited use.
If you'll be building up a String by concatenating, and aren't using e.g. StringBuiler, your code can begin as one of the following.
String result = new String();
String result = "";
String result = "first part of string";
// ...
result += "append to the result";
The first two aren't equivalent, and you should prefer to initialize with "" since this can take advantage of string interning.
Small example... String can be garbage collected
System.out.println(1 + new String() + 2);
instead of
System.out.println(1 + "" + 2);
According to the documentation, this constructor creates an empty sequence.
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.
If you want an empty sequence, it makes sense.
But normally, it wouldn't be necessary to use the empty constructor before you make changes to it, since you are not changing the String. In fact, when you change using the operator += for example, you are creating another immutable String, and not changing one.
Check this question about this subject: How do String objects work (like immutable objects)?
Some background first
Because Strings in Java are immutable, they are also "interned" - that means that all the string literals in the loaded classes are kept in a pool, so there is usually only one instance of each unique string literal in memory at one time. It is an application of the flyweight pattern, similar pools are also kept for Integer and other primitive wrapper objects (but only for a limited number of small values).
Because of this mechanism, identity comparison of string literals (even from different classes) is usually possible (although you should always use equals method when comparing strings for safety and consistency):
System.out.println("hello" == "hello"); // true
Now, if you use the default string constructor, you get an instance of an empty string, but it is a new instance, as stated in JavaDoc:
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.
Such new instance is different from the interned empty string, resulting in:
System.out.println(new String() == ""); // false
But as I said, only string literals are automatically interned - that means strings created manually by StringBuilders, from char arrays etc. are not interned. You can use the String.intern() method to put such a string into the pool manually.
Now for some real scenario
Well all this is nice indeed, but I still haven't answered why this constructor exists. Well, Java strings are just smart wrappers over char arrays and some distinct string objects can share their internal arrays.
If I create a very long string (by reading from a stream for example), then this instance isn't interned (as said above), so it will be garbage collected after the variable that referenced it gets out of scope. But if do this:
String longString = readVeryLongString();
String shortString = longString.subString(0, 10);
... then the new shortString will not copy first 10 characters from the longString and put them into its own new char array. No, it will reference the original array, using only first 10 chars from it.
Now, if the shortString variable has longer life (for example is put into some static context), then the underlying char array will not be garbage collected (even if the original longString variable already got out of scope). This is one of the ways how to create a memory leak in Java.
Now, the default string constructor comes to the rescue! If I change the code above to this:
String longString = readVeryLongString();
String shortString = new String(longString.subString(0, 10));
... then the shortString will be a new string instance that made a new internal char array by copying only the 10 required chars from the original string returned by the subString method.
A nice article illustrating this subject:
http://illya-keeplearning.blogspot.cz/2009/03/java-string-internals.html
to create an empty string,call default constructor as
String s new String();
will create an instance of String with no characters in it.
If I run,
String s1="abc";
then are there any differences between:
String s2=new String(s1);
and
String s2="abc";
Here's what I'm confused about:
The Head First Java says:"If there's already a String in the String pool with the same value, the JVM doesn't create a duplicate, it simply refers your reference variable to the existing entry. " Which at my point of view is that the s1 has already created "abc",s2 just refers to it. Am I right??
When you write String s2="abc"; and "abc" is already in the pool, then you won't get a duplicate - you'll get a reference to the existing String.
But if you write new String(something), you get a new String, whether there's a matching String in the pool or not.
String Constant Pool comes into picture in this case as shown in below screenshot.
I think it will help you to understand it visually.
String s1="abc"; // s1 will go to String constant pool
String s2=new String(s1); // any object created by "new" keyword will go to Heap
String s2="abc"; // s1 and s2 both will refer to same string in constant pool
the new keyword will force to create a new string object in heap even it already exist in string pool
This question already has answers here:
How many objects are being created? [duplicate]
(2 answers)
Closed 9 years ago.
How many string objects will be created by the following code?
String s="";
s+=new String("a");
s+="b";
I had this question at exam. I want to know the right answer . I said 2 objects.
The object from pool that contains "" , "b" and the object created by new String("a");
I'll anwser to another, clearer question: how many String instances are involved in the following code snippet:
String s="";
s+=new String("a");
s+="b";
And the answer is 6:
the empty String literal: "";
the String literal "a";
the copy of the String literal "a": new String("a");
the String created by concatenating s and the copy of "a";
the String literal "b"
the String created by concatenating s and "b".
If you assume that the three String literals have already been created by previously-loaded code, the code snippet thus creates 3 new String instances.
String s="";
creates no objects.
s+=new String("a");
creates five objects. the new String, the StringBuilder and its char[] and the String resulting and its char[]
s+="b";
creates four objects, the StringBuilder and its char[] and the String resulting and its char[]
So I get a total of nine objects of which are three String objects
Note: You can be sure that "" has already been loaded as it appear in many system classes including ClassLoader and Class.
The Strings "a" and "b" may or may not be considered as new Strings for the purpose of this question. IMHO I wouldn't count them as they will only be created at most once and if this code is only run once, it hardly matters how many strings are created. What is more likely to be useful is to know how many objects are created each time the code is run.
The number of objects actually created in a JITC situation is indeterminate. The JITC may well recognize that new String("a") is an identity, and that no intermediate values of s are referenced, so that only the StringBuilder is created. There are several potential side-effects that must be mimicked in the general case (eg, where the argument to new String() may be invalid), but with literals they can't occur.
In fact, javac could very well recognize that the result is "ab", with no potential side-effects, and just produce a String literal of that value. (It does string combining in slightly less complicated cases.)
Creating New Strings
Earlier we promised to talk more about the subtle differences between the various methods of creating a String. Let's look at a couple of examples of how a String might be created, and let's further assume that no other String objects exist in the pool:
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.
From SCJP Sun Certified Programmer for Java 6 Study Guide (Exam 310-065).pdf
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
String object creation using new and its comparison with intern method
I was playing around with Strings to understand them more and I noticed something that I can't explain :
String str1 = "whatever";
String str2 = str1;
String str3 = "whatever";
System.out.println(str1==str2); //prints true...that's normal, they point to the same object
System.out.println(str1==str3); //gives true..how's that possible ?
How is the last line giving true ? this means that both str1 and str3 have the same address in memory.
Is this a compiler optimization that was smart enough to detect that both string literals are the same ("whatever") and thus assigned str1 and str3 to the same object ? Or am I missing something in the underlying mechanics of strings ?
Because Java has a pool of unique interned instances, and that String literals are stored in this pool. This means that the first "whatever" string literal is exactly the same String object as the third "whatever" literal.
As the Document Says:
public String intern()
Returns a canonical representation for the
string object. A pool of strings, initially empty, is maintained
privately by the class String.
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.
It follows that for any two strings s and t, s.intern() == t.intern()
is true if and only if s.equals(t) is true.
All literal strings and string-valued constant expressions are
interned. String literals are defined in ยง3.10.5 of the Java Language
Specification
Returns: a string that has the same contents as this string, but is
guaranteed to be from a pool of unique strings.
http://www.xyzws.com/Javafaq/what-is-string-literal-pool/3
As the post says:
String allocation, like all object allocation, proves costly in both time and memory. The JVM performs some trickery while instantiating string literals to increase performance and decrease memory overhead. To cut down the number of String objects created in the JVM, the String class keeps a pool of strings. Each time your code create a string literal, the JVM checks the string literal pool first. If the string already exists in the pool, a reference to the pooled instance returns. If the string does not exist in the pool, a new String object instantiates, then is placed in the pool.
If you do:
String str1 = new String("BlaBla"); //In the heap!
String str2 = new String("BlaBla"); //In the heap!
then you're explicitly creating a String object through new operator (and constructor).
In this case you'll have each object pointing to a different storage location.
But if you do:
String str1 = "BlaBla";
String str2 = "BlaBla";
then you've implicit construction.
Two strings literals share the same storage if they have the same values, this is because Java conserves the storage of the same strings! (Strings that have the same value)
The javac compiler combines String literals which are the same in a given class file.
However at runtime, String literals are combined using the same approach as String.intern() This means even Strings in different class in different applications (in the same JVM which use the same object.