Ответ 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)
, когда старое поведение было оправдывая это.