Нет необходимости вызывать super ().
Из Доступ к членам суперкласса :
При использовании super () вызывается конструктор суперкласса без аргументов. С super (список параметров) вызывается конструктор суперкласса с соответствующим списком параметров.
Примечание. Если конструктор не вызывает явно конструктор суперкласса, компилятор Java автоматически вставляет вызов в конструктор суперкласса без аргументов. Если у суперкласса нет конструктора без аргументов, вы получите ошибку во время компиляции. У Object действительно есть такой конструктор, поэтому, если Object является единственным суперклассом, проблем нет.
Конструкция 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
Это различие важно, но начинающим программистам обычно лучше не знать об этом слишком много. Использование StringBuilder
, когда вы много строите строки, - это хорошо, но часто ваше приложение будет иметь гораздо больше проблем, а небольшой прирост производительности StringBuilder
незначителен. Остерегайтесь программистов, которые говорят вам, что все манипуляции со строками должны выполняться с использованием StringBuilder.
В качестве очень грубого практического правила: StringBuilder требует некоторых затрат на создание, но добавление стоит недорого. Стоимость создания строки низкая, но объединение обходится относительно дорого. Переломный момент составляет около 400-500 конкатенаций, в зависимости от размера: после этого StringBuilder становится более эффективным.
РЕДАКТИРОВАТЬ: на основе комментария Конрада Рудольфа, я добавил это section.
Если предыдущее эмпирическое правило заставляет вас задуматься, String.Format
, ToString
и другие строковые операции, использование StringBuilder в таких случаях вряд ли когда-либо эффективно.
Итак, когда это эффективно? В случаях, когда добавляется много маленьких строк, например, для сериализации данных в файл, и когда вам не нужно изменять «записанные» данные после «записи» в StringBuilder. И в тех случаях, когда многим методам нужно что-то добавлять, потому что StringBuilder является ссылочным типом, а строки копируются при их изменении.
Проблема возникает - не только с младшими программистами - когда они пытаются сделать эталонное сравнение и выясните, что иногда результат верный, а иногда ложный в, казалось бы, одних и тех же ситуациях. Что случилось? Когда строки были интернированы компилятором и добавлены в глобальный статический интернированный пул строк, сравнение двух строк может указывать на один и тот же адрес памяти. Когда (ссылка!) Сравнение двух равных строк, одна интернированная, а другая нет, даст false. Используйте сравнение =
или Equals
и не экспериментируйте с ReferenceEquals
при работе со строками.
В той же лиге соответствует странному поведению, которое иногда происходит при использовании 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
? С объектами это имеет смысл, но со строками - нет.
Единственное отличие, которое действительно имеет значение для большинства кодов, - это тот факт, что null
может быть присвоено строковым переменным.
Неизменяемый класс действует как тип значения во всех обычных ситуациях, и вы можете довольно много программировать, не особо заботясь о различиях.
Это когда вы копаете немного глубже и заботиться о производительности, которую вы действительно используете для различия. Например, чтобы знать, что хотя передача строки в качестве параметра методу действует так, как если бы была создана копия строки, на самом деле копирование не происходит. Это может быть сюрпризом для людей, привыкших к языкам, в которых строки на самом деле являются типами значений (например, VB6?), И передача большого количества строк в качестве параметров не будет хорошей производительностью.
Строка - это особый вид. Это ссылочный тип, но он используется большинством кодировщиков как тип значения. Сделав его неизменяемым и используя внутренний пул, он оптимизирует использование памяти, которое будет огромным, если это чистый тип значения.
Дополнительные материалы здесь:
C # .NET String объект действительно по ссылке? on SO
String.Intern Метод в MSDN
строка (справочник C #) в MSDN
Обновление:
См. комментарий abel
к этому сообщению. Это исправило мое вводящее в заблуждение заявление.