как работает функция subString () класса string - PullRequest
1 голос
/ 01 апреля 2009

см. Следующий код.

String s = "Monday";
if(s.subString(0,3).equals("Mon"){}

String s2 = new String(s.subString(0,3));
String s3 = s.subString(0,3);  

Я знаю, что строка 2 по-прежнему будет указывать на «Понедельник» и будет иметь новый объект String со смещением и счетчиком, установленными на 0,3.

Строка 4 создаст новую строку "Mon" в пуле строк и укажет на нее.

Но не уверен насчёт строки 5, будет ли она вести себя как строка 2 или строка 4.

Если я ошибаюсь в строке 2 или 4, пожалуйста, исправьте ..

Ответы [ 7 ]

9 голосов
/ 01 апреля 2009

Как указал Пит Киркхэм, это зависит от реализации. Мой ответ верен только для Sun JRE и только до Java 7, обновление 6.

Вы правы относительно обычного substring вызова, просто создающего новую строку, ссылающуюся на тот же массив символов, что и исходная строка. Это то, что происходит в строке 5 тоже. Тот факт, что новая ссылка на строковый объект назначается переменной, не меняет поведения метода.

Просто чтобы прояснить ситуацию, вы говорите, что в строке 2 новая строка будет по-прежнему указывать на "Monday" - ссылка на массив char внутри строки будет соответствовать тому же массиву char, который используется для "Monday". Но «понедельник» сам по себе является строкой, а не массивом символов. Другими словами, к моменту окончания строки 2 (и игнорирования GC) появляются два строковых объекта, оба ссылаются на один и тот же массив символов. Один имеет счет 6, а другой - 3; оба имеют смещение 0.

Вы ошибаетесь в строке 4, используя "пул строк" - там не происходит объединение. Тем не менее, он отличается от других линий. Когда вы вызываете конструктор String(String), новая строка принимает копию символьных данных оригинала, поэтому она полностью отделена. Это может быть очень полезно, если вам нужна только строка, которая содержит небольшую часть очень большой исходной строки; он позволяет собирать мусор в исходном большом массиве символов (при условии, что он больше не нужен), пока вы держите копию небольшой части. Хорошим примером этого в моем собственном опыте является чтение строк из строки. По умолчанию BufferedLineReader будет читать строки, используя буфер из 80 символов, поэтому каждая возвращаемая строка будет использовать массив символов длиной не менее 80 символов. Если вы читаете много очень коротких строк (отдельных слов), разница в потреблении памяти заключается только в использовании странного

line = new String(line);

может быть очень значительным.

Это помогает?

7 голосов
/ 01 апреля 2009

Я знаю, что строка 2 по-прежнему будет указывать на «Понедельник» и будет иметь новый объект String со смещением и счетчиком, установленными на 0,3.

Это в настоящее время верно для реализации Sun JRE. Кажется, я вспоминаю, что это не относится к реализации Sun в прошлом и не относится к другим реализациям JVM. Не полагайтесь на поведение, которое не указано. GNU classpath может скопировать массив (я не могу вспомнить, какое соотношение используется, чтобы решить, когда копировать, но он копирует, если копия является достаточно маленькой частью оригинала, что превратило один хороший алгоритм O (N) в O (N ^ 2)).

Строка 4 создаст новую строку "Mon" в пуле строк и укажет на нее.

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

Конструктор String(String) говорит:

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

Конструктор String(char[]) сообщает:

Выделяет новую строку, чтобы она представляла последовательность символов, в настоящее время содержащуюся в аргументе массива символов. содержимое массива символов скопировано; последующая модификация массива символов не влияет на вновь созданную строку.

Следуя хорошим принципам ОО, ни один метод String на самом деле не требует, чтобы он был реализован с использованием массива символов, поэтому ни одна часть спецификации String не требует операций с массивом символов. Те операции, которые принимают массив в качестве входных данных, указывают, что содержимое массива копируется в любое внутреннее хранилище, используемое в строке. Строка может использовать сжатие UTF-8 или LZ внутри и соответствовать API.

Однако, если ваша JVM не выполняет оптимизацию подстроки с малым отношением, тогда есть вероятность, что она скопирует только соответствующую часть, когда вы используете new String(String), так что это случай, если вы попробуете это улучшает использование памяти. Не все, что влияет на время выполнения Java, определяется Java.

Чтобы получить строку в пуле строк, равную equal строке, используйте метод intern(). Это либо извлечет строку из пула, если она уже была интернирована, либо создаст новую строку и поместит ее в пул. Обратите внимание, что объединенные строки имеют другое (опять-таки зависящее от реализации) поведение сборки мусора.

3 голосов
/ 14 ноября 2012

Примечание : Начиная с Java 7, обновление 6 в Sun / Oracle Java, больше не верно, что String, созданный String.substring, совместно использует массив char родительского элемента. Было решено, что такая оптимизация редко бывала полезной и не оправдывала стоимость и сложность полей offset и count.

Некоторые ссылки:

1 голос
/ 01 апреля 2009

В строке 5 ----> s3 = Пн.

0 голосов
/ 26 января 2019

«Подстрока создает новый объект из исходной строки, беря часть исходной строки».

До Java 1.7 подстрока содержит ссылку на исходный символьный массив, что означает, что даже подстрока длиной 5 символов может препятствовать массиву символов в 1 ГБ из-за сбора мусора, удерживая сильную ссылку.

Эта проблема исправлена ​​в Java 1.7, где на исходный символьный массив больше не ссылаются, но это изменение также делало создание подстроки битом с точки зрения времени. Ранее это было в диапазоне O (1), который мог быть O (n) в худшем случае на Java 7.

enter image description here

0 голосов
/ 01 апреля 2009

В реализации Sun строковые объекты имеют поле private final char value[]. Когда вы создаете новую строку с помощью функции substring (), новый массив символов не создается, новый экземпляр использует value исходного объекта. Это имеет место в строках 2 и 5, новые объекты String будут использовать массив символов s.

Конструктор String (String) создает новый массив char в случае, если длина строки меньше общей длины массива char value. Поэтому строка, созданная в строке 4, будет использовать новый массив символов.

Вы должны взглянуть на исходный код конструктора public String (String original), это действительно просто.

0 голосов
/ 01 апреля 2009

прочитайте это http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html

"Возвращает новую строку ..."

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...