В классе String отсутствуют методы, которые позволяли бы изменять символы в существующей строке. Так, если требуется заменить символьную строку в переменной greeting с "Help! ", этого нельзя добиться одной лишь заменой двух последних символов. Программирующим на С это покажется, по меньшей мере, странным. "Как же видоизменить строку?" — спросят они. В Java внести необходимые изменения можно, выполнив сцепление подстроки, которую требуется сохранить, с заменяющими символами, как показано ниже.
greeting = greeting.substring(0, 3) + "р!";
В итоге переменной greeting присваивается символьная строка "Help!".
Программируя на Java, нельзя изменять отдельные символы в строке, поэтому в документации объекты типа String называются неизменяемыми, т.е. постоянными. Как число 3 всегда равно 3, так и строка "Hello" всегда состоит из последовательности кодовых единиц символов ?Н', !е!, Ч1, '1' и 'о1. Изменить ее состав нельзя. Но, как мы только что убедились, можно изменить содержимое строковой переменной greeting и заставить ее ссылаться на другую символьную строку подобно тому, как числовой переменной, в которой хранится число 3, можно присвоить число 4.
Не приводит ли это к снижению эффективности кода? Казалось бы, намного проще изменять символы, чем создавать новую строку заново. Возможно, это и так. В самом деле, неэффективно создавать новую строку путем сцепления символьных строк "Hel" и "р! ". Но у неизменяемых строк имеется одно существенное преимущество: компилятор может сделать строки совместно используемыми.
Чтобы стал понятнее принцип постоянства символьных строк, представьте, что в общем пуле находятся разные символьные строки. Строковые переменные указывают на объекты в этом пуле. При копировании строковой переменной оригинал и копия содержат одну и ту же общую последовательность символов. Логично не прибегать к дублированию строк, а поместить в переменные ссылки на одну и ту же область памяти. Одним словом, создатели языка Java решили, что эффективность совместного использования памяти перевешивает неэффективность редактирования строк путем выделения подстрок и сцепления.
Посмотрите на свои программы. Мы подозреваем, что чаще всего вы не изменяете символьные строки, а сравниваете их. Разумеется, бывают случаи, когда непосредственные манипуляции символьными строками оказываются более эффективными. Одна из таких ситуаций возникает, когда нужно составить строку из отдельных символов, поступающих из файла или с клавиатуры. Для подобных ситуаций в языке Java предусмотрен отдельный класс StringBuf fer, рассматриваемый далее в разделе "Построение строк", а в остальном достаточно средств, предоставляемых в классе String.
НА ЗАМЕТКУ С++! Когда программирующие на С обнаруживают символьные строки в программе на Java, они обычно попадают в тупик, поскольку привыкли рассматривать строки как массивы символов: char greeting[] = "Hello";
Это не совсем подходящая аналогия: символьная строка в Java больше напоминает указатель char*:
char* greeting = "Hello";
При замене содержимого переменной greeting другой символьной строкой в коде Java выполняется примерно следующее:
char* temp = malloc(6); strncpy(temp, greeting, 4); strncpy(temp + 4, "!", 2); greeting = temp;
Разумеется, теперь переменная greeting указывает на строку "Help!". И даже самые убежденные поклонники языка С должны признать, что синтаксис Java более изящный, чем последовательность вызовов функции strncpyO. А что, если присвоить переменной greeting еще одно строковое значение, как показано ниже?
Для любого бизнеса необходимы рекламные материалы. Будь то визитки или например листовки с фирменным логотипом должны быть обязательно. Если у вас их еще нет то изготовление листовок вы найдете тут. Вы можете заказать как оптом так и не большое количество листовок.
greeting = "Howdy";
Не возникнут ли при этом утечки памяти? К счастью, в Java имеется механизм автоматической "сборки мусора". Если память больше не нужна, она в конечном итоге освобождается.
Если вы программируете на С++ и применяете класс string, определенный в стандарте ANSI С++, вам будет намного легче работать с объектами типа String в Java. Объекты класса string в С++ также обеспечивают автоматическое выделение и освобождение памяти. Управление памятью осуществляется явным образом с помощью конструкторов, деструкторов и операций присваивания. Но символьные строки в С++ являются изменяемыми, а это означает, что отдельные символы в строке можно видоизменять. |