Притворство строки.NET является типом значения

Нет необходимости вызывать super ().

Из Доступ к членам суперкласса :

При использовании super () вызывается конструктор суперкласса без аргументов. С super (список параметров) вызывается конструктор суперкласса с соответствующим списком параметров.

Примечание. Если конструктор не вызывает явно конструктор суперкласса, компилятор Java автоматически вставляет вызов в конструктор суперкласса без аргументов. Если у суперкласса нет конструктора без аргументов, вы получите ошибку во время компиляции. У Object действительно есть такой конструктор, поэтому, если Object является единственным суперклассом, проблем нет.

7
задан Dinah 2 November 2009 в 00:11
поделиться

4 ответа

Конструкция string s была намеренно такой, что вам не нужно слишком сильно беспокоиться об этом как программисту. Во многих ситуациях это означает, что вы можете просто присваивать, перемещать, копировать, изменять строки, не задумываясь о возможных сложных последствиях, если другая ссылка на вашу строку существовала и была бы изменена одновременно (как это происходит со ссылками на объекты).

Строковые параметры в вызове метода

(РЕДАКТИРОВАТЬ: этот раздел добавлен позже)
Когда строки передаются в метод, они передаются по ссылке. Когда они читаются только в теле метода, ничего особенного не происходит. Но когда они изменяются, создается копия, и временная переменная используется в остальной части метода. Этот процесс называется копированием при записи .

Младших беспокоит то, что они привыкли к тому, что объекты являются ссылками, и они изменяются в методе, который изменяет переданный параметр. Чтобы сделать то же самое со строками, им необходимо использовать ключевое слово ref . Это фактически позволяет изменить ссылку на строку и вернуть ее вызывающей функции. Если вы этого не сделаете, строка не может быть изменена телом метода:

void ChangeBad(string s)      { s = "hello world"; }
void ChangeGood(ref string s) { s = "hello world"; }

// in calling method:
string s1 = "hi";
ChangeBad(s1);       // s1 remains "hi" on return, this is often confusing
ChangeGood(ref s1);  // s1 changes to "hello world" on return

On StringBuilder

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

В качестве очень грубого практического правила: StringBuilder требует некоторых затрат на создание, но добавление стоит недорого. Стоимость создания строки низкая, но объединение обходится относительно дорого. Переломный момент составляет около 400-500 конкатенаций, в зависимости от размера: после этого StringBuilder становится более эффективным.

Подробнее о StringBuilder и производительности строк

РЕДАКТИРОВАТЬ: на основе комментария Конрада Рудольфа, я добавил это section.

Если предыдущее эмпирическое правило заставляет вас задуматься, String.Format , ToString и другие строковые операции, использование StringBuilder в таких случаях вряд ли когда-либо эффективно.

Итак, когда это эффективно? В случаях, когда добавляется много маленьких строк, например, для сериализации данных в файл, и когда вам не нужно изменять «записанные» данные после «записи» в StringBuilder. И в тех случаях, когда многим методам нужно что-то добавлять, потому что StringBuilder является ссылочным типом, а строки копируются при их изменении.

Об интернированных строках

Проблема возникает - не только с младшими программистами - когда они пытаются сделать эталонное сравнение и выясните, что иногда результат верный, а иногда ложный в, казалось бы, одних и тех же ситуациях. Что случилось? Когда строки были интернированы компилятором и добавлены в глобальный статический интернированный пул строк, сравнение двух строк может указывать на один и тот же адрес памяти. Когда (ссылка!) Сравнение двух равных строк, одна интернированная, а другая нет, даст false. Используйте сравнение = или Equals и не экспериментируйте с ReferenceEquals при работе со строками.

On String.Empty

В той же лиге соответствует странному поведению, которое иногда происходит при использовании String.Empty : статический String.Empty всегда интернируется, а переменная с присвоенным значением - нет. Однако по умолчанию компилятор назначит String.Empty и укажет на тот же адрес памяти. Результат: изменяемая строковая переменная, по сравнению с ReferenceEquals , возвращает true, в то время как вы можете ожидать вместо этого false.

// emptiness is treated differently:
string empty1 = String.Empty;
string empty2 = "";
string nonEmpty1 = "something";
string nonEmpty2 = "something";

// yields false (debug) true (release)
bool compareNonEmpty = object.ReferenceEquals(nonEmpty1, nonEmpty2);

// yields true (debug) false (release, depends on .NET version and how it's assigned)
bool compareEmpty = object.ReferenceEquals(empty1, empty2);

Подробно

Вы в основном спрашивали, какие ситуации могут возникнуть у непосвященных. Я думаю, что моя точка зрения сводится к тому, чтобы избегать object.ReferenceEquals , потому что ему нельзя доверять при использовании со строками. Причина в том, что интернирование строки используется, когда строка является постоянной в коде, но не всегда. На такое поведение нельзя полагаться. Хотя String.Empty и "" всегда интернированы, это не так, когда компилятор считает, что значение можно изменить. Различные варианты оптимизации (отладка против выпуска и другие) дадут разные результаты.

Когда сделать , вам все равно понадобится ReferenceEquals ? С объектами это имеет смысл, но со строками - нет.

17
ответ дан 6 December 2019 в 07:27
поделиться

Единственное отличие, которое действительно имеет значение для большинства кодов, - это тот факт, что null может быть присвоено строковым переменным.

3
ответ дан 6 December 2019 в 07:27
поделиться

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

Это когда вы копаете немного глубже и заботиться о производительности, которую вы действительно используете для различия. Например, чтобы знать, что хотя передача строки в качестве параметра методу действует так, как если бы была создана копия строки, на самом деле копирование не происходит. Это может быть сюрпризом для людей, привыкших к языкам, в которых строки на самом деле являются типами значений (например, VB6?), И передача большого количества строк в качестве параметров не будет хорошей производительностью.

3
ответ дан 6 December 2019 в 07:27
поделиться

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

Дополнительные материалы здесь:
C # .NET String объект действительно по ссылке? on SO
String.Intern Метод в MSDN
строка (справочник C #) в MSDN

Обновление:
См. комментарий abel к этому сообщению. Это исправило мое вводящее в заблуждение заявление.

1
ответ дан 6 December 2019 в 07:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: