Вопрос-ответ

What is the purpose of the expression "new String(...)" in Java?

Какова цель выражения "новая строка (...)" в Java?

Просматривая онлайн-примеры кода, я иногда сталкивался с присвоением строковой константы объекту String с помощью оператора new .

Например:

String s;
...
s = new String("Hello World");

Это, конечно, по сравнению с

s = "Hello World";

Я не знаком с этим синтаксисом и понятия не имею, какова будет цель или эффект.
Поскольку строковые константы обычно хранятся в пуле констант, а затем в любом представлении, которое JVM имеет для работы со строковыми константами, будет ли что-нибудь вообще размещено в куче?

Переведено автоматически
Ответ 1

Единственное место, где вы можете подумать, что хотите new String(String), - это принудительно создать отдельную копию внутреннего массива символов, как в

small=new String(huge.substring(10,20))

Однако, к сожалению, такое поведение недокументировано и зависит от реализации.

Я был поражен этим, когда считывал большие файлы (некоторые размером до 20 Мбайт) в строку и разделял ее на строки постфактум. В итоге я получил все строки для строк, ссылающихся на char[], состоящие из всего файла. К сожалению, это непреднамеренно сохранило ссылку на весь массив для нескольких строк, которые я удерживал в течение более длительного времени, чем обработка файла - я был вынужден использовать new String(), чтобы обойти это, поскольку обработка 20 000 файлов очень быстро потребляла огромное количество оперативной памяти.

Единственный независимый от реализации способ сделать это:

small=new String(huge.substring(10,20).toCharArray());

Для этого, к сожалению, необходимо скопировать массив дважды, один раз для toCharArray() и один раз в конструкторе String .

Должен быть документированный способ получения новой строки путем копирования символов существующей; или документация String(String) должна быть улучшена, чтобы сделать ее более явной (там есть подтекст, но он довольно расплывчатый и открытый для интерпретации).

Ошибка предположения о том, чего в документе не указано

В ответ на комментарии, которые продолжают поступать, обратите внимание, какой была реализация Apache Harmony new String():

public String(String string) {
value = string.value;
offset = string.offset;
count = string.count;
}

Это верно, там нет копии базового массива. И все же, он по-прежнему соответствует документации по строкам (Java 7), поскольку он:


Инициализирует вновь созданный объект String таким образом, чтобы он представлял ту же последовательность символов, что и аргумент; другими словами, вновь созданная строка является копией строки аргумента. Если не требуется явная копия оригинала, использование этого конструктора не требуется, поскольку строки неизменяемы.


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

Будьте осторожны, чтобы программировать на основе документации, а не одной реализации.

Ответ 2

Единственный раз, когда я нашел это полезным, - это при объявлении переменных блокировки:

private final String lock = new String("Database lock");

....

synchronized(lock)
{
// do something
}

В этом случае инструменты отладки, такие как Eclipse, будут показывать строку при перечислении того, какие блокировки поток в данный момент удерживает или ожидает. Вы должны использовать "новую строку", т. Е. Выделить новый строковый объект, потому что в противном случае общий строковый литерал может быть заблокирован в каком-либо другом несвязанном коде.

Ответ 3

Строка s1="foo"; литерал будет отправлен в StringPool, а s1 будет ссылаться.

Строка s2 = "foo"; на этот раз он проверит, доступен ли литерал "foo" в StringPool или нет, поскольку сейчас он существует, поэтому s2 будет ссылаться на тот же литерал.

Строка s3 = новая строка ("foo"); сначала в StringPool будет создан литерал "foo", затем с помощью конструктора string arg будет создан строковый объект, т. е. "foo" в куче из-за создания объекта с помощью оператора new, затем s3 будет ссылаться на него.

Строка s4= новая строка ("foo"); такая же, как s3

итак, System.out.println(s1==s2); //true из-за буквального сравнения.

и System.out.println(s3==s4);// false из-за сравнения объектов (s3 и s4 создаются в разных местах кучи)

Ответ 4

Единственная утилита для этого конструктора, описанная Software Monkey и Ruggs, похоже, исчезла из JDK7. В классе String больше нет offset поля, и substring всегда использует

Arrays.copyOfRange(char[] original, int from, int to) 

обрезать массив символов для копирования.

java string