Использование конструктора String (String) в Java

Я читал статьи и книги, что использование String s = new String("..."); следует избегать почти все время. Я понимаю, почему это так, но можно ли использовать конструктор String (String)? Я не думаю, что есть, и не вижу никаких доказательств в обратном порядке, но мне интересно, знает ли кто-нибудь в коммюнике SO об использовании.


Точный дубликат: какова цель выражения новой строки в java?

Это хорошая статья: конструктор String, который считается бесполезным, оказывается полезным в конце концов!

Оказывается, этот конструктор действительно может быть полезен, по крайней мере, в одном случае. Если вы когда-либо заглядывали в исходный код String, вы увидите, что у него есть не только поля для значения массива символов и количества символов, но также и для смещения к началу строки. Это значит, что Strings могут совместно использовать значение массива char с другими строками, как правило, это результат вызова одного из методов substring (). Java был classно наказан за это в jwz ‘Java rant из лет назад:

Единственная причина для этих накладных расходов заключается в том, что String.substring () может возвращать строки, которые имеют один и тот же массив значений. Выполнение этого за счет добавления 8 байт к каждому объекту String не является чистой экономией …

Сохранение байтов в сторону, если у вас есть такой код:

 // imagine a multi-megabyte string here String s = "0123456789012345678901234567890123456789"; String s2 = s.substring(0, 1); s = null; 

Теперь у вас будет String s2, который, хотя и представляет собой односимвольную строку, содержит ссылку на массив гигантских символов, созданный в String s. Это означает, что массив не будет собирать мусор, хотя мы явно вытеснили строку s!

Исправить это, чтобы использовать наш ранее упоминавшийся «бесполезный» конструктор String следующим образом:

 String s2 = new String(s.substring(0, 1)); 

Не известно, что этот конструктор фактически копирует это старое содержимое в новый массив, если старый массив больше, чем количество символов в строке. Это означает, что старое содержимое String будет собираться мусором, как предполагалось. Счастливая радостная радость.

Наконец, Кэт Марсен делает эти пункты,

Прежде всего, строковые константы никогда не собираются в мусор. Во-вторых, строковые константы являются intern’d, что означает, что они разделены по всей виртуальной машине. Это экономит память. Но это не всегда то, что вы желаете.

Конструктор копирования в String позволяет создать частный экземпляр String из строкового литерала. Это может быть очень полезно для создания значимых объектов мьютекса (для синхронизации).

Если я правильно помню, единственным «полезным» случаем является то, что исходная строка является частью гораздо большего массива поддержки. (например, создается как подстрока). Если вы хотите, чтобы небольшая подстрока и мусор собирали большой буфер, может возникнуть смысл создать новую строку.

Просто чтобы расширить ответ Дагласа *, я могу привести убедительный пример того, где я его использовал. Подумайте о чтении словарного файла с тысячами строк, каждое из которых – всего лишь одно слово. Самый простой способ прочитать это – использовать BufferedReader.readLine() .

К сожалению, readLine() выделяет буфер по 80 символов по умолчанию в качестве ожидаемой длины строки. Это означает, что обычно это может избежать бессмысленного копирования – и немного потерянной памяти обычно не так уж плохо. Однако, если вы загружаете словарь коротких слов в течение всего срока действия приложения, вы получаете огромное количество памяти, которая постоянно теряется. Мое «маленькое приложение» всасывало гораздо больше памяти, чем следовало делать.

Решение состояло в том, чтобы изменить это:

 String word = reader.readLine(); 

в это:

 String word = new String(reader.readLine()); 

… с комментарием, конечно!

* Я не помню, работал ли я с Дугласом, когда это произошло, или просто случайно он ответил на этот конкретный вопрос.

Конструктор в значительной степени избыточен и не рекомендуется для общих целей. Строковый конструктор с аргументом String редко используется, кроме как для создания независимой копии существующей строковой переменной. В основном использовать его для «уточнения» вашего кода. Не меньше.

от javadoc

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

Вы используете его, если вам нужна копия исходной строки, если вы не хотите указывать дескриптор исходной строки. Но поскольку строки неизменяемы, я не вижу случая использования этого 😉

Давайте будем гением компьютера.