This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
What is the purpose of the expression “new String(…)” in Java?
It's immutable, why would you need to invoke String.String(String str) ?
From the API doc:
Unless an explicit copy of original is needed, use of this constructor is
unnecessary since Strings are immutable.
The only reason I can think of is in the situation where:
You've created a very large String: A.
You've created a small substring: B based on A. If you look at the implementation of substring you'll see it references the same char[] array as the original string.
String A has gone out of scope and you wish to reduce memory consumption.
Creating an explicit copy of B will mean that the copy: B' no longer references the large char[]. Allowing B to go out of scope will allow the garbage collector to reclaim the large char[] that backs A and B, leaving only the small char[] backing B'.
new String(s) can help garbase collection:
String huge = ...;
String small = s.substring(0,2); //huge.value char[] is not garbage collected here
String gcFriendly = new String(small); //now huge.value char[] can be garbage collected
Just in case you need String that are not the same but equal.
Maybe for testing to make sure, people really do str.equals(str2) instead of (str == str2). But I never needed it.
Related
String str = new String(“my literal”);
In above statement ,two objects would be created ,one as String literal “my literal” in string constant pool (If it's not present in string pool) and other in heap area as object String(“my literal”)
Q-1 I know the benefit of putting the string literal in string pool area but I am not able to think of about the benefit of creating a duplicate object in heap?
Q2- As I read in some stack over flow link: If use of new String("my literal") is almost always bad because you will be creating 2 Strings one on String constants pool and another on heap with the same value ,then my question is why does Java creates duplicate object in heap? Why not java just ignore creating in heap?
There is almost no benefit to calling the String(String) constructor with a literal string. There used to be a significant benefit to calling the String(String) constructor with a different string expression.
The literal is already a String, and String objects are immutable. More generally, for any String expression passed to the String(String) constructor, the constructor is usually unnecessary, because the argument is already an immutable String.
From the String(String) constructor documentation:
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.
With older versions of Java (prior to 1.7.0_06), the String(String) constructor was more useful. A String created by String.substring() could refer to the larger original String, and prevent it from being garbage collected. The String(String) constructor cut the ties to the larger String.
You asked:
Q-1: ... The benefit of creating a duplicate object in heap?
Usually there is none. However, if you're using a String object in a context where object identity matters, you might want a different object. For example:
You're using String objects as keys within a IdentityHashMap, and want only your own String objects to match.
You want to synchronize on a string value provided by external code. You don't want any other code synchronizing on the same String object; it could lead to unexpected interference and deadlock. [This example provided by #biziclop in a comment below.]
Q-2: ... why does Java creates duplicate object in heap?
Because you explicitly asked it to with new String("my literal"). If you use the new operator, you get a new object.
Everyone knows that Java's String object is immutable which essentially means that if you take String object a and concatenate it with another String object, say b, a totally new String object is created instead of an inplace concatenation.
However, recently I have read this question on SO which tells that the concatenation operator + is replaced with StringBuilder instances by the compiler.
At this point, I get a bit confused since, as far as I know and think, the StringBuilder objects are mutable due to their internal structure. In this case, wouldn't this essentially make String objects in Java mutable ?
Not really.
The actual Strings are still immutable, but in compile time, the JVM can detect some situations where the creation of additional String objects can be replaced by a StringBuilder.
So if you declare a String a and concatenate with another String, your a object doesn't change, (since it's immutable), but the JVM optimizes this by replacing the concatenation with the instantiation of a StringBuilder, appending both Strings to the Builder, and finally assigning the resulting String.
Let's say you have:
String a = "banana";
String d = a + "123" + "xpto";
Before the JVM optimized this, you would essentially be creating a relatively large number of Strings for something so simple, namely:
String a
String "123"
String "xpto"
String a + "123"
String a+"123"+"xpto"
With the optimization of transforming concatenation into a StringBuilder, the JVM no longer needs to create the intermediate results of the concatenation, so only the individual Strings and the resulting one are needed.
This is done basically for performance reasons, but keep in mind that in certain situations, you'll pay a huge penalty for this if you aren't careful. For instance:
String a = "";
for(String str: listOfStrings){
a += str;
}
If you were doing something like this, in each iteration the JVM will be instantiating a new StringBuilder, and this will be extremely costly if listOfStrings has a lot of elements. In this case, you should use a StringBuilder explicitly and do appends inside the loop instead of concatenating.
Strings are immutable objects. Once you concatenate it with another String, it becomes a new object. So remember - you don't change the existing String, you just create a new one.
Strings really are immutable. The compiler may generate code involving StringBuilder, but that is just an optimization which does not change how the code behaves (apart from performance). If there was some case where you could observe mutation (e.g. by keeping a reference to one of the intermediate results), the compiler would have to optimize in a way that still gives you an immutable string for that intermediate reference.
So if StringBuilder is used under the covers, even if you can't directly see the difference, doesn't that still mean that mutability is involved? Well, yes, but if you get down to it all the RAM in your PC is mutable. The memory of immutable objects can be moved around by the garbage collector, which definitely involves mutation as well. In the end, the important thing to you as a programmer is that this mutation is hidden from you, and you get a big promise that your program will behave the way you expect, i.e. you'll never see mutation in an immutable object (except in cases of severe problems, e.g. faulty RAM).
If we take a look at the String#substring method implementation :
new String(offset + beginIndex, endIndex - beginIndex, value);
We see that a new String is created with the same original content (parameter char [] value).
So the workaround is to use new String(toto.substring(...)) to drop the reference to the original char[] value and make it eligible for GC (if no more references exist).
I would like to know if there is a special reason that explain this implementation. Why the method doesn't create herself the new shorter String and why she keeps the full original value instead?
The other related question is : should we always use new String(...) when dealing with substring?
I would like to know if there is a special reason that explain this implementation. Why the method doesn't create herself the new shorter String and why she keeps the full original value instead?
Because in most use-cases it is faster for substring() to work this way. At least, that's what Sun / Oracle's empirical measurements would have shown. By doing this, the implementation avoids allocating a backing array and copying characters to the array.
This is only a non-optimization if you have to then copy the String to avoid a memory leakage problem. In the vast majority of cases, the substrings become garbage in a relatively short period of time, and there is no long-term leakage of memory.
Hypothetically, the Java designers could have provided two versions of substring, one which behaved as currently, and the other that created a String with its own backing array. But that would encourage the developer to waste brain-cycles thinking about which version to use. And then there's the problem of utility methods that build on substrings ... like the Pattern / Matcher classes for instance. So I think it is a good thing that they didn't.
Because String is immutable class
Also See
http://javarevisited.blogspot.it/2010/10/why-string-is-immutable-in-java.html (Courtesy: Luca Geretti )
The reason for this implementation is efficiency. By pointing to the same char[] as the original string, no data needs to be copied.
This does have a downside though, as you've already hinted at yourself. If the original string is long and you just want to get a small part of it, and you don't need the original string anymore after that, then the complete original array is still referenced and can't be garbage collected. You already know how to avoid that - do new String(original.substring(...)).
should we always use new String(...) when dealing with substring?
No, not always. Only when you know it might cause problem. In many cases, referring to the original char[] instead of copying the data is more efficient.
Why there is no reverse method in String class in Java? Instead, the reverse() method is provided in StringBuilder? Is there a reason for this? But String has split(), regionMatches(), etc., which are more complex than the reverse() method.
When they added these methods, why not add reverse()?
Since you have it in StringBuilder, there's no need for it in String, right? :-)
Seriously, when designing an API there's lots of things you could include. The interfaces are however intentionally kept small for simplicity and clarity. Google on "API design" and you'll find tons of pages agreeing on this.
Here's how you do it if you actually need it:
str = new StringBuilder(str).reverse().toString();
Theoretically, String could offer it and just return the correct result as a new String. It's just a design choice, when you get down to it, on the part of the Java base libraries.
If you want an historical reason, String are immutable in Java, that is you cannot change a given String if not creating another String.
While this is not bad "per se", initial versions of Java missed classes like StringBuilder. Instead, String itself contained (and still contains) a lot of methods to "alter" the String but since String is immutable, each of these methods actually creates and return a NEW String object.
This caused simple expressions like :
String s = "a" + anotherString.substr(10,5).trim().toLowerCase();
To actually create in ram something like 5 strings, 4 of which are absolutely useless, with obvious performance problems (despite after there has been some optimizations regarding underlying char[] arrays).
To solve this, Sun introduced StringBuilder and other classes that ARE NOT immutable. These classes freely modify a single char[] array, so that calling methods does not need to produce many intermediate String instances.
They added "reverse" quite lately, so they added it to StringBuilder instead of String, cause that's now the preferred way to manipulate strings.
As a side-note, in Scala you use the same java.lang.String class and you do get a reverse method (along with all kinds of other handy stuff). The way it does it is with implicit conversions, so that your String gets automatically converted into a class that does have a reverse method. It's really quite clever, and removes the need to bloat the base class with hundred of methods.
String is immutable, meaning it can't be changed.
When you reverse a String, what's happening is that each letter is switched on it's own, means it will always create the new object each times.
Let us see with example:
This means that for instance Hello becomes as below
elloH lloeH loleH olleH
and you end up with 4 new String objects on the heap.
So think if you have thousands latter of string or more then how much object will be created.... it will be really a very expensive. So too much memory will be occupied.
So because of this String class not having reverse() method.
Well I think it could be because it is an immutable class so if we had a reverse method it would actually create a new object.
reverse() acts on this, modifying the current object, and String objects are immutable - they can't be modified.
It's peculiarly efficient to do reverse() in situ - the size is known to be the same, so no allocation is necessary, there are half as many loop iterations as there would be in a copy, and, for large strings, memory locality is optimal. From looking at the code, one can see that a lot of care was taken to make it fast. I suspect the author(s) had a particular use case in mind that demanded high performance.
Is using a String() constructor as against string literal beneficial in any scenario?
Using string literals enable reuse of existing objects, so why do we need the public constructor? Is there any real world use?
For eg., both the literals point to the same object.
String name1 = "name";//new String("name") creates a new object.
String name2 = "name";
One example where the constructor has a useful purpose: Strings created by String.substring() share the underlying char[] of the String they're created by. So if you have a String of length 10.000.000 (taking up 20MB of memory) and take its first 5 characters as substring then discard the original String, that substring will still keep the 20MB object from being eligible for garbage collection. Using the String constructor on it will avoid that, as it makes a copy of only the part of the underlying char array that's actually used by the String instance.
Of course, if you create and use a lot of substrings of the same String, especially if they overlap, then you'd very much want them to share the underlying char[], and using the constructor would be counterproductive.
Since string is immutable, operations like substring keep the original string that might be long. Using the constructor to create new string from the substring will create a new string and will allow dropping the old string (to GC). This way might free up needed memory.
Example:
String longS = "very long";
String shortS = new String(longS.substring(4));
Because sometimes you might want to create a copy and not just have a new reference to the same string.
All good answers here, but I think it's worth pointing out that the Java treats literals quite different than Strings constructed the traditional way.
This is a good Q/A about it.