Java. Полное руководство. 8-е издание. С. Н. Тригуб Перевод с английского и редакция
Скачать 25.04 Mb.
|
ГЛАВА Обработка строк Краткий обзор обработки строк в Java был приведен в главе 7. В этой главе мы рассмотрим эту тему подробнее. Как ив других языках программирования, в Java строка — это последовательность символов. Нов отличие от некоторых других языков, в которых строки реализованы как массивы символов, в Java строки являются объектами класса Реализация строк в виде встроенных объектов позволяет Java предоставить полный комплект средств, обеспечивающих удобство управления строками. Например, Java предоставляет методы для сравнения двух строк, поиска подстрок, объединения двух строки изменения регистра символов в строке. Кроме того, объекты класса String могут быть созданы множеством разных способов, что позволяет легко получать строки, когда они требуются. Что несколько неожиданно, так это тот факт, что, создавая объект класса String, вы получаете строку, которая не может быть изменена. Иными словами, как только объект класса String создан, вы не можете изменить символы, образующие строку. На первый взгляд это может показаться серьезным ограничением. Однако на самом деле это не так уж важно. Вы можете выполнять со строками любые операции. Особенность в том, что всякий раз, когда вам нужна измененная версия существующей строки, создается новый объект класса String, включающий все модификации. Оригинальная строка остается неизменяемой. Этот подход используется потому, что фиксированная, неизменяемая, строка может быть реализована более эффективно, нежели изменяемая. Для тех случаев, когда нужны модифицируемые строки, Java предлагает на выбор два класса StringBuf f er и StringBuilder. Оба содержат строки, которые могут быть изменены после того, как созданы. Классы String, StringBuf f er и StringBuilder определены в пакете java. lang. Поэтому они доступны всем программистам автоматически. Все они объявлены с модификатором final, следовательно, ни от одного из них нельзя получить подклассы. Это позволяет осуществить некоторую оптимизацию, повышающую производительность общих операций со строками. Все три класса реализуют интерфейс И последнее когда говорится о том, что строки в объектах класса String не изменяемы, это означает, что содержимое экземпляра строки не может быть изменено после его создания. Однако переменная, объявленная как ссылка на класс String, в любой момент может быть переназначена так, чтобы указывать на другой объект класса String. 3 9 Часть II. Библиотека Конструкторы строк Класс S t r i n g поддерживает несколько конструкторов. Чтобы создать пустой объект класса S t r i n g , вызывается стандартный конструктор. Например, следующий оператор создает экземпляр класса S t r i n g , не содержащий в себе символов s = new Stri n g O Зачастую требуется создать строку, которая содержит начальное значение. Класс S t r i n g предлагает множество конструкторов для этого. Чтобы создать строку, инициализированную массивом символов, используйте следующий конструктор символы []) Вот примеры c h ars[] = { ас Этот конструктор инициализирует строку s символами " a b c "С помощью следующего конструктора в качестве инициализирующей строки вы можете задать диапазон символьного массива символы ], int начИ ндекс, int количСимволов) Здесь на чИндекс указывает начало диапазона, а количСимволов — количество символов, которые нужно использовать c h ars[] = { асе, Это инициализирует строку s символами lhc d e "Используя конструктор, вы можете создать объект класса S t r i n g , который содержит туже последовательность символов, что и другой объект класса S t r i n g . String(String стрОбъект) Здесь стрОбъект — это объект класса S t r i n g . Рассмотрим следующий пример Создать один объект String из другого class MakeString { public static void main(String a r g s []) { char с [] = {'J', ' a ' , ' v ' , 'a'}; String si = new String(c); String s2 = new String(sl);' System.out.println(s i ); System.out.p r intln(s 2 Вывод этой программы будет выглядеть так. Java Java Как видите, строки s i и s2 содержат одинаковые значения. Даже несмотря на то, что тип Java c h a r использует 16 бит для представления базового набора символов Unicode, типичный формат строк в Интернете использует массивы битовых байтов, созданных из набора символов ASCII. Поскольку битовые строки ASCII употребляются наиболее часто, класс S t r i n g предлагает конструкторы, которые инициализируют строки массивом типа b y te . Их форма приведена ниже символы biibАbiibб с И [ ]) String(byte символы biibАbiibб с И [ ], int начИндекс, int количСимволов) Глава 15. Обработка строк 3 9 Здесь параметр символы Абс И представляет массив байтов. Вторая форма позволяет вам указать диапазон. В каждом из этих конструкторов преобразование байтов в символы выполняется в соответствии с кодировкой по умолчанию для конкретной платформы. Применение этих конструкторов иллюстрируется в следующей программе Создание строки из подмножества символьного массива class SubStringCons { public static void main(String a r g s []) { byte a s c i i [] = {65, 66, 67, 68, 69, 70 }; String si = new String(ascii); System.out.println(si); String s2 = new String(ascii, 2, 3); System.out.println(s 2 Ниже показан вывод этой программы. ABCDEF CDE Существуют также расширенные версии конструкторов “байт-строка”, в которых вы можете указать кодировку символов, определяющую способ преобразования байтов в символы. Однако, как правило, вам подойдет кодировка для данной платформы по умолчанию. На заметку Содержимое массива копируется всякий раз, когда вы создаете объект класса string из массива. Если вы модифицируете содержимое массива после создания строки ваш объект класса string останется неизменяемым. Вы можете создать объект класса String из объекта класса StringBuf fer, используя следующий конструктор o6beK TStrB u Вы можете создать строку из объекта класса StringBuilder, используя следующий конструктор o 6 b e K T S t rB u ild Следующий конструктор поддерживает расширенный набор символов Unicode. String(int кодов ы еТочк и int начИндекс, int количСимволов) Здесь кодовыеТочки— массив, содержащий символы Unicode. Результирующая строка создается из диапазона, начинающегося с начИндекс и имеющего длину количСимволов. Существуют также конструкторы, позволяющие определять набор символов. На заметку Обсуждение элементов кода Unicode и способов работы сними в Java можно найти в главе Длина строки Количество символов, из которых состоит строка, определяет ее длину. Чтобы получить это значение, вызовите метод length (). int Следующий фрагмент выводит " 3 м, поскольку именно три символа содержит строка s. 3 9 Часть II. Библиотека Java char cha r s [] = { 'a', 'b', 'c' }; String s = new Специальные строковые операции Поскольку строки — общая и важная часть программирования, язык Java обеспечивает специальную поддержку некоторых строковых операций в рамках синтаксиса языка. Эти операции включают автоматическое создание новых экземпляров класса S t r i n g из строковых литералов, конкатенацию множества объектов класса S t r i n g с помощью оператора +, а также преобразование других типов данных в строковое представление. Существуют явные методы для реализации всех этих функций, но язык Java также выполняет их автоматически для удобства программистов и большей ясности. Строковые литералы В предыдущих примерах было показано, как явным образом создавать объекты класса S t r i n g из массива символов с помощью оператора new. Однако есть более простой способ сделать это с помощью строковых литералов. Для каждого строкового литерала в вашей программе Java автоматически создается объект класса S t r i n g . Таким образом, вы можете использовать строковый литерал для инициализации объекта класса S t r i n g . Например, следующий фрагмент кода создает две эквивалентные строки chars[] = { ас используется строковый литерал Поскольку объект класса S t r i n g создается для каждого строкового литерала, вы можете использовать литерал в любом месте, где допускается применение объекта класса S t r i n g . Например, вы можете вызывать методы непосредственно со строками в кавычках, как если бы они были ссылками на объекты, что показано в следующем примере. Здесь вызывается метод l e n g t h () для строки " a b c ". Как и ожидалось, он возвращает значение Конкатенация строк В общем случае язык не позволяет применять операторы к объектам класса S t r i n g . Одно исключение из правил — применение оператора +, который соединяет две строки, порождая в результате объект класса S t r i n g . Это позволяет соединять вместе серии операторов +. Например, в следующем фрагменте кода осуществляется конкатенация трех строк age = "9"; String s = "Ему " + age + " лет."; System.out.println(s); В результате отображается строка " Ему 9 лет Глава 15. Обработка строк 3 9 Одно практическое применение конкатенации строк — когда вы создаете очень длинные строки. Вместо того чтобы включать в код длинные строки одним куском, вы можете разбить их на маленькие фрагменты, используя оператор + для конкатенации Использование конкатенации во избежание длинных строк class ConCat { public static void main(String a r g s []) { String longStr = "Это может быть " +очень длинная строка, которую следует " + перенести. Но конкатенация позволяет " + предотвратить это Конкатенация строк с другими типами данных Вы можете соединять строки сданными других типов. Например, рассмотрим слегка измененную версию предыдущего примера age = 9; String s = "Ему " + age + " лет r intln(s В этом случае переменная age имеет типа не String, но результат получается тот же, что и раньше. Так происходит потому, что значение типа int автоматически преобразуется в строковое представление в объекте класса String. После этого строки конкатенируются, как и прежде. Компилятор преобразует операнды в их строковые эквиваленты, в то время как другие операнды оператора + являются экземплярами класса Будьте внимательны, когда смешиваете операнды других типов со строками в выражениях конкатенации. В противном случае можно получить весьма неожиданные результаты. Рассмотрим следующий код s = "четыре " + 2 + Этот фрагмент отображает четыре: 22 вместо четыре что вы, вероятно, и ожидали. И вот почему. Приоритеты операторов обеспечивают вначале конкатенацию "четыре" со строковым эквивалентом числа 2. Результат затем конкатенируется со строковым эквивалентом второго числа 2. Чтобы вначале выполнить целочисленное сложение, следует применить скобки s = " четыре " + (2 + Теперь строка s содержит символы " четыре "Преобразование строки метод t o S t r i n g ( При конкатенации Java преобразует данные в строковое представление вызовом одной из перегруженных версий преобразующих методов valueOf () , определенных в классе String. Метод valueOf () перегружен для всех элементарных типов и для типа Ob j ect. Для элементарных типов метод valueOf () возвращает 3 9 8 Часть II. Библиотека строку, которая содержит читабельный для человека эквивалент значения, с которым он был вызван. Для объектов метод valueOf () вызывает метод t o S t r i n g () этого объекта. Более подробная информация о методе valueOf () приведена далее в этой главе. А сейчас давайте изучим метод t o S t r i n g () как средство строкового представления объектов классов, которые вы создадите. Каждый класс реализует метод t o S t r i n g ( ), поскольку этот метод определен в классе O b je c t. Однако реализация метода t o S t r i n g () по умолчанию редко может быть полезной. Для всех наиболее важных, создаваемых вами классов вы пожелаете переопределить метод t o S t r i n g () и обеспечить собственное строковое представление. К счастью, это легко сделать. Общий метод t o S t r i n g () имеет следующую форму Чтобы реализовать его, просто возвратите объект класса String, который содержит читабельную для человека строку, адекватно описывающую объект вашего класса. Переопределяя метод t o S t r i n g () для создаваемых вами классов, вы позволяете им полностью интегрироваться в программное окружение Java. Например, они могут применяться в операторах p r i n t () и p r i n t l n ( ) , а также в строковых выражениях с конкатенацией. Следующая программа демонстрирует это, переопределяя метод t o S t r i n g () для класса Box. // Переопределение метода toString() для класса Box. class Box { double width; double height; double depth; Box(double w, double h, double d) { width = w; height = h; depth = d; } public String toString() { return "Размеры " + width + " на " + depth + " на " + height + "."; } } class toStringDemo { public static void main(String a r g s []) { Box b = new B o x (10, 12, 14); String s = "Box b: " + b; // конкатенация объекта Box System.out.println(b); // преобразование Box в строку System.out.println(s); } } Вывод этой программы выглядит так. Размеры 10.0 на 14.0 на 12.0 Box b: Размеры 10.0 на 14.0 на Извлечение символов Класс String предлагает множество способов извлечения символов из объекта класса String. Некоторые из них мы рассмотрим. Хотя символы, которые составляют строку, не могут быть индексированы подобно тому, как это делается в символьных массивах, однако многие методы класса String используют индек Глава 15. Обработка строк 3 9 9 сы (или смещения) в строке для выполнения своих операций. Подобно массивам, строки индексируются начиная с нуля. Метод charAt (Чтобы выделить из строки единственный символ, вы можете обратиться к нему непосредственно, с помощью метода c h a rA t ( ), который имеет следующую общую форму charAt(int где Здесь где — индекс символа, который нужно получить. Значение где должно быть неотрицательными указывать положение в строке. Метод c h a rA t () возвращает символ, находящийся в указанном положении. Например ch; ch = "присваивает значение "b" переменной Метод getChars (Если нужно извлечь более одного символа сразу, вы можете применить метод g e tC h a r s (), который имеет следующую общую форму getChars (int начИсточника , int конИ сточника , char цель [ ] , int начЦели) Здесь начИсточника указывает индекс начала подстроки, а конИсточника — индекс символа, следующего за концом извлекаемой подстроки. Таким образом, извлекается подстрока, содержащая символы от начИсточника до конИсточника- 1. Массив, который принимает выделенные символы, указан в параметре цель Индекс в массиве цель, начиная с которого будет записываться подстрока, передается в параметре начЦели. Следует позаботиться о том, чтобы массив цель был достаточного размера, чтобы в нем поместились все символы указанной подстроки. В следующей программе демонстрируется использование метода g e tC h a r s (). class getCharsDemo { public static void main(String a r g s []) { String s = "Это демонстрация метода getChars."; int start = 4; int end = 8; char buf[] = new char[end - start]; s .getChars(start, end, buf, Вывод программы показан ниже. демо Метод getBytes (Существует альтернатива методу g e tC h a r s ( ) , которая сохраняет символы в массив байтов. Это метод g e tB y te s ( ), который использует преобразование символов в байты по умолчанию, предоставляемое платформой. Вот его простейшая форма getBytes() Часть II. Библиотека Доступны также другие формы этого метода. Метод getBytes(),B основном, применим тогда, когда вы экспортируете значения типа String в среды, которые не поддерживают битовые символы Unicode. Например, большинство протоколов Интернет и форматов текстовых файлов используют битовый код ASCII для всех текстовых взаимодействий., Метод t o C h a r A r r a y ( Если хотите преобразовать все символы в объекте класса String в символьный массив, то простейший способ сделать это — вызвать метод toChar Array (). Он возвращает массив символов для всей строки. Его общая форма такова Эта функция представлена в качестве дополнения, поскольку тот же результат можно получить, применив метод get Chars (Сравнение строк Класс String включает множество методов, предназначенных для сравнения строк или подстрок в строках. Рассмотрим здесь некоторые из них. Методы e q u a l s ( ) и e q u a l s l g n o r e C a s e ( Чтобы сравнить две строки на эквивалентность, используйте метод equals (). Он имеет следующую общую форму equals(Object строка) Здесь строка — это объект класса String, который сравнивается с вызывающим объектом класса String. Метод возвращает значение true, если строка содержит те же символы ив том же порядке, и значение false — в противном случае. Сравнение зависит от регистра. Чтобы выполнить сравнение, игнорирующее регистр символов, вызовите метод equalslgnoreCase () . Когда этот метод сравнивает две строки, он рассматривает диапазон А -Z как тоже самое, что и a-z. Он имеет следующую общую форму, boolean equalslgnoreCase(Object строка) Здесь строка — это объект класса String, который сравнивается с вызывающим объектом класса String. Метод также возвращает значение true, если строки содержат одинаковые символы в том же порядке, и значение false — в противном случае. Вот пример, демонстрирующий применение методов equals () и equals lgnoreCase (). |