0

After executing String S1 = "hello"; JVM will create a String object in SCP and that object will hold an array of char in value field like

s1.value = {'h', 'e', 'l', 'l', 'o'}

And when we say

String s2 = new String("hello");

And according to the source code of String class after constructor execution s2.value will also become "hello".value which will be similar to s1.value.

public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}

So every time we create String object using new JVM will create

  1. one object in heap and
  2. one string literal object in SCP if it already not there

And the object in heap points to the literal object in SCP internally.

And every time, we make a change in s2 or in any other string (doesn't matter it is created from literal or using new) one new string literal will get created on the heap, which that newly changed s2 will point.

Using String s2 = new String("hello") is not creating "hello" object in heap. JVM is creating "hello" in SCP only if it is not present there and s2 pointing to it.

My question is not, what is the difference between new String("hello") or simple "hello".

My question is when using public String(String original) is just creating empty string object in heap and wasting memory Why Java allows developers to call public String(String original) and why is it even provided in String class, what benefit it is giving?

Naresh Joshi
  • 4,188
  • 35
  • 45

1 Answers1

1

There is an interesting statement in Joshua Bloch’s “Effective Java”, 2nd edition, chapter 4, item 15:

A consequence of the fact that immutable objects can be shared freely is that you never have to make defensive copies (Item 39). In fact, you never have to make any copies at all because the copies would be forever equivalent to the originals. Therefore, you need not and should not provide a clone method or copy constructor (Item 11) on an immutable class. This was not well understood in the early days of the Java platform, so the String class does have a copy constructor, but it should rarely, if ever, be used (Item 5).

(page 76 in my copy)
I think, Joshua Bloch can be seen as an authoritative source, especially as James Gosling, one of the Java inventors, has been cited saying, “I sure wish I had this book ten years ago…” (referring to the 1st edition from 2001).


So the existence of the String(String) constructor can be seen as a design mistake, much as the parameterless String() constructor. Note also the presence of the factory methods String.valueOf(char[])/ String.valueOf(char[],int,int) and String.copyValueOf(char[])/ String.copyValueOf(char[],int,int), whose naming suggests a fundamental difference that simply isn’t there. The immutable nature of String mandates that all variants create a defensive copy of the provided array, to protect against subsequent modifications. So the behavior is exactly the same (the documentation tells this explicitly), whether you use valueOf or copyValueOf.


That said, there are some practical use cases, though not necessarily being within original intentions. Some of them are described in the answers to this question. As the new operation guarantees to produce a new instance, it might be useful for any subsequent operation relying on a distinct identity, e.g. synchronizing on that instance (not that this was a good idea) or trying to recognize that instance via identity comparison to be sure that it doesn’t originate from an external source. E.g., you might want to distinguish between a property’s default value and a value that has been explicitly set. This, however, is of limited use as other code might not guaranty to maintain the object identity in its operations, even if the string contents doesn’t change. Or it might remember your special instance and reuse it, once it encountered the string.

Before Java 7, update 6, String had an offset and length field, allowing a cheap substring operation, referring to a range within the original array, without copying. This led to the scenario, that a (conceptually) small string could hold a reference to a rather large array, preventing its garbage collection. For the reference implementation (that shipped by Sun/later Oracle), recreating the string via the String(String) constructor produced a String with a fresh copy of the array, occupying only as much memory as needed. So this was a use case incorporating an implementation specific fix to an implementation specific problem…

Current Java releases do not maintain these offset and length fields, implying a potentially more expensive substring operation, but no copying behavior in the String(String) constructor anymore. This is the version, whose source code you have cited in the question. The older version can be found in this answer.

Community
  • 1
  • 1
Holger
  • 285,553
  • 42
  • 434
  • 765
  • so for current version java 8, the copy constructor of the string is completely useless, and even decreasing the performance of your java application – Naresh Joshi Nov 22 '16 at 07:47