Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why String class has copy constructor? [duplicate]

Tags:

java

Possible Duplicate:
What is the purpose of the expression “new String(…)” in Java?

If immutable classes objects copies would be equal to the originals then why does the String class in Java have a copy constructor? Is it a mistake or there is a reason behind this implementation? In the Java docs it is specified that:

/**
 * Initializes a newly created {@code 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 {@code original} is needed, use of this constructor is
 * unnecessary since Strings are immutable.
 *
 * @param  original
 *         A {@code String}
 */
 public String(String original) {
 ....
 ....}
like image 373
Prateek Avatar asked Dec 10 '12 15:12

Prateek


People also ask

Does Java String class have a copy constructor?

Like C++, Java also supports a copy constructor.

What is the purpose of copy constructor?

A copy constructor in a Java class is a constructor that creates an object using another object of the same Java class. That's helpful when we want to copy a complex object that has several fields, or when we want to make a deep copy of an existing object.

Why copy constructor is not used in Java?

In C++ that statement makes a copy of the object's state. In Java it simply copies the reference. The object's state is not copied so implicitly calling the copy constructor makes no sense. And that's all there is to it really.

What is the alternative for copy constructor in Java?

Copy Constructor Vs clone() Method Both the copy constructor and the clone() method are used to create a copy of an existing object of the class.


1 Answers

The main reason to copy a string is to "trim the baggage", that is to trim the underlying char array to only what is necessary.

The underlying char array can mainly be too big because when you create a string by calling substring, the char array can be shared between the new string instance and the source string instance; an offset points to the first character and the length is included.

The expression I use, "trim the baggage", is taken from the source code of String copying constructor :

  164       public String(String original) {
  165           int size = original.count;
  166           char[] originalValue = original.value;
  167           char[] v;
  168           if (originalValue.length > size) {
  169               // The array representing the String is bigger than the new
  170               // String itself.  Perhaps this constructor is being called
  171               // in order to trim the baggage, so make a copy of the array.
  172               int off = original.offset;
  173               v = Arrays.copyOfRange(originalValue, off, off+size);
  174           } else {
  175               // The array representing the String is the same
  176               // size as the String, so no point in making a copy.
  177               v = originalValue;
  178           }
  179           this.offset = 0;
  180           this.count = size;
  181           this.value = v;

This is something many developers forget and is important because a small string may prevent the garbaging of a bigger char array. See this related question where I already pointed this : Java not garbage collecting memory. Many developers consider than the decision of Java designers to use this old optimization trick that was familiar to C coders did, in fact, more harm than good. Many of us know it because we were bitten by it and did have to look into Sun's source code to understand what happened...

As Marko points out (see comments below), in OpenJDK, starting from java 7 Update 6, substring doesn't share the char array anymore and the String(String) constructor is, thus, useless. But it's still fast (even faster in fact) and as this change hadn't been propagated to all VM (and probably not all your customers) I'd recommend to keep this best-practice to use new String(substring) when the old behavior was justifying it.

like image 198
Denys Séguret Avatar answered Sep 19 '22 06:09

Denys Séguret