Почему класс String имеет конструктор копирования?

Возможный дубликат:
Какова цель выражения "new String (...)" в Java?

Если копии объектов неизменяемых объектов будут равны оригиналам, то почему класс String в Java имеет конструктор копирования? Является ли это ошибкой или есть причина этой реализации? В документах Java указано, что:

/**
 * 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) {
 ....
 ....}

Ответы

Ответ 1

Основная причина копирования строки - "обрезать багаж", то есть обрезать базовый массив char только для того, что необходимо.

Основной массив char может быть в основном слишком большим, потому что, когда вы создаете строку, вызывая substring, массив char может быть разделен между новым экземпляром строки и экземпляром исходной строки; смещение указывает на первый символ и включается длина.

Выражение, которое я использую, "обрезать багаж", берется из исходного кода конструктора копирования String:

  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;

Это то, что многие разработчики забывают и важно, потому что небольшая строка может помешать мусору большего массива char. См. Этот связанный вопрос, где я уже указывал на это: Java, а не сборщик мусора. Многие разработчики считают, что решение Java-дизайнеров использовать этот старый трюк оптимизации, который был знаком C-кодерам, на самом деле был больше вреда, чем пользы. Многие из нас знают это, потому что нас укусили, и мне пришлось изучить исходный код Sun, чтобы понять, что произошло...

Как указывает Марко (см. комментарии ниже), в OpenJDK, начиная с java 7 Update 6, substring больше не использует массив char, а конструктор String(String), таким образом, бесполезен. Но все еще быстро (даже быстрее) и поскольку это изменение не было распространено на всех виртуальных машинах (и, возможно, не на всех ваших клиентов), я бы рекомендовал использовать эту лучшую практику для использования new String(substring), когда старое поведение было оправдывая это.