Работа со строками
Глава 9 Работа со строками
В этой главе обсуждаются средства языка Java для работы со строками. В языках С и C++ отсутствует встроенная поддержка такого объекта, как строка. В них при необходимости передается адрес последовательности байтов, содержимое которых трактуется как символы до тех пор, пока не будет встречен нулевой байт, отмечающий конец строки. В пакет java.lang встроен класс, инкапсулирующий структуру данных, соответствующую строке. Этот класс, называемый String, не что иное, как объектное представление неизменяемого символьного массива. В этом классе есть методы, которые позволяют сравнивать строки, осуществлять в них поиск и извлекать определенные символы и подстроки. Класс StringBuffer используется тогда, когда строку после создания требуется изменять.
ВНИМАНИЕ
И String, и StringBuffer объявлены final, что означает, что ни от одного из этих классов нельзя производить подклассы. Это было сделано для того, чтобы можно было применить некоторые виды оптимизации позволяющие увеличить производительность при выполнении операций обработки строк.
Конструкторы
Как и в случае любого другого класса, вы можете создавать объекты типа String с помощью оператора new. Для создания пустой строки используется конструктор без параметров:
String s = new String():
Приведенный ниже фрагмент кода создает объект s типа String инициализируя его строкой из трех символов, переданных конструктору в качестве параметра в символьном массиве.
char chars[] = { 'а', 'b', 'с' }:
String s = new String(chars);
System.out.println(s):
Этот фрагмент кода выводит строку «abc». Итак, у этого конструктора — 3 параметра:
String(char chars[], int начальныйИндекс, int числоСимволов);
Используем такой способ инициализации в нашем очередном примере:
char chars[] = { 'a', 'b', 'с', 'd', 'e', 'f' }:
String s = new String(chars,2,3);
System.out.println(s);
Этот фрагмент выведет «cde».
Специальный синтаксис для работы со строками
В Java включено несколько приятных синтаксических дополнений, цель которых — помочь программистам в выполнении операций со строками. В числе таких операций создание объектов типа String слияние нескольких строк и преобразование других типов данных в символьное представление.
Создание строк
Java включает в себя стандартное сокращение для этой операции — запись в виде литерала, в которой содержимое строки заключается в пару двойных кавычек. Приводимый ниже фрагмент кода эквивалентен одному из предыдущих, в котором строка инициализировалась массивом типа char.
String s = "abc";
System.out.println(s);
Один из общих методов, используемых с объектами String — метод length, возвращающий число символов в строке. Очередной фрагмент выводит число 3, поскольку в используемой в нем строке — 3 символа.
String s = "abc";
System.out.println(s.length);
В Java интересно то, что для каждой строки-литерала создается свой представитель класса String, так что вы можете вызывать методы этого класса непосредственно со строками-литералами, а не только со ссылочными переменными. Очередной пример также выводит число 3.
System.out.println("abc".Length());
Слияние строк
Строку
String s = «Не is » + age + " years old.";
в которой с помощью оператора + три строки объединяются в одну, прочесть и понять безусловно легче, чем ее эквивалент, записанный с явными вызовами тех самых методов, которые неявно были использованы в первом примере:
String s = new StringBuffer("He is ").append(age);
s.append(" years old.").toString();
По определению каждый объект класса String не может изменяться. Нельзя ни вставить новые символы в уже существующую строку, ни поменять в ней одни символы на другие. И добавить одну строку в конец другой тоже нельзя. Поэтому транслятор Java преобразует операции, выглядящие, как модификация объектов String, в операции с родственным классом StringBuffer.
ЗАМЕЧАНИЕ
Все это может показаться вам необоснованно сложным. А почему нельзя обойтись одним классом String, позволив ему вести себя примерно так же, как StringBuffer? Все дело в производительности. Тот факт, что объекты типа String в Java неизменны, позволяет транслятору применять к операциям с ними различные способы оптимизации.
Последовательность выполнения операторов
Давайте еще раз обратимся к нашему последнему примеру:
String s = "Не is " + age + " years old.";
В том случае, когда age — не String, а переменная, скажем, типа int, в этой строке кода заключено еще больше магии транслятора. Целое значение переменной int передается совмещенному методу append класса StringBuffer, который преобразует его в текстовый вид и добавляет в конец содержащейся в объекте строки. Вам нужно быть внимательным при совместном использовании целых выражений и слияния строк, в противном случае результат может получиться совсем не тот, который вы ждали. Взгляните на следующую строку:
String s = "four: " + 2 + 2;
Быть может, вы надеетесь, что в s будет записана строка «four: 4»? Не угадали — с вами сыграла злую шутку последовательность выполнения операторов. Так что в результате получается "four: 22".
Для того, чтобы первым выполнилось сложение целых чисел, нужно использовать скобки :
String s = "four: " + (2 + 2);
Преобразование строк
В каждом классе String есть метод toString — либо своя собственная реализация, либо вариант по умолчанию, наследуемый от класса Object. Класс в нашем очередном примере замещает наследуемый метод toStrring своим собственным, что позволяет ему выводить значения переменных объекта.
class Point {
int х, у;
Point(int x, int у) {
this.x = х;
this.у = у;
}
public String toString() {
return "Point[" + x + ", " + у + "]";
} }
class toStringDemo {
public static void main(String args[]) {
Point p = new Point(10, 20);
System.out.println("p = " + p);
} }
Ниже приведен результат, полученный при запуске этого примера.