Конкатенация других типов данных
Операцию конкатенации строк можно использовать с другими типами данных. Например, рассмотрим следующую, немного измененную, версию предыдущего примера:
int age = 9;
String s = "Ему " + age + " лет.";
System.out.println(s);
В этом случае переменная age — имеет int-тип, а не string, как в предыдущем фрагменте, но вывод — такой же, как прежде. Это потому, что int-значение переменной age автоматически преобразуется в ее строчное представление внутри string-объекта и затем сцепляется аналогичным способом. Компилятор преобразует операнд операции конкатенации к его строчному эквиваленту всякий раз, когда другой операнд этой операции является экземпляром (объектом) типа string.
Однако будьте внимательны, когда смешиваете другие типы операций в выражениях конкатенации строк. Вы можете получить неожиданные результаты. Рассмотрим следующий фрагмент:
String s = "четыре: " + 2 + 2;
System.out.println(s);
Этот фрагмент выводит на экран:
четыре: 22
а не
четыре: 4
как вы, вероятно, ожидали. И вот, почему. С учетом старшинства операций сначала выполняется конкатенация первого операнда ("четыре:") со строчным эквивалентом второго ("2"). Этот результат затем сцепляется со строчным эквивалентом третьего операнда (тоже "2"). Чтобы выполнить сначала целочисленное сложение, нужно использовать круглые скобки:
String s = "четыре: " + (2+2);
Теперь s содержит строку "четыре: 4".
Преобразование строк и метод toString()
Когда во время конкатенации данные преобразуются в их строчное представление, вызывается одна из перегруженных версий метода преобразования строк valueof(), определенного в классе string, valueof() перегружен для всех простых типов и для типа object. Для простых типов valueof() возвращает строку, которая содержит удобочитаемый эквивалент значения, для которого он вызывается. Для объектов valueof() вызывает метод toString(). Мы рассмотрим valueof() подробнее позже. Здесь же познакомимся с методом toString(), потому что это средство, с помощью которого вы можете определять строчное представление для объектов тех классов, которые вы создаете в своей программе.
Каждый класс реализует toString(), поскольку данный метод определен в классе object. Однако реализации toString(), заданной по умолчанию, редко достаточно. Для наиболее важных классов, которые вы создаете сами, нужно переопределять toString() и обеспечивать тем самым свои собственные строчные представления объектов. К счастью, это делается достаточно просто. Метод toString() имеет следующую общую форму:
String toString()
Реализация toString() просто возвращает объект типа string, который содержит удобочитаемую строку, описывающую объект вашего класса.
Переопределяя toString() для создаваемых вами классов, вы получаете строчные представления объектов, полностью интегрированные в среду программирования Java. Например, они могут использоваться в операторах print() и printin() и в выражениях конкатенации. Следующая программа демонстрирует это, переопределяя toString() для Вох-классов:
// Переопределение toString() для Вох-классов.
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 "Размеры Box-объекта: " + width + " x " + depth + " x " + height + ".";
}
}
class toStringDemo {
public static void main(String args [] ) {
Box b = new Box(10, 12, 14);
String s = "Box b: " + b; // конкатенация Box-объекта
System.out.println(b); // преобразование Box-объекта в строку
System.out.println(s);
}
}
Вывод этой программы:
Размеры Box-объекта: 10 х 14 х 12.
Box b: Размеры Box-объекта: 10 х 14 х 12.
Обратите внимание, что метод toString() вызывается автоматически, когда Box-объект используется в выражении конкатенации или в обращении к println().
Извлечение символов
Класс String предоставляет несколько способов извлечения символов из объекта типа String. Хотя символы, которые составляют строку String-объекта, не могут быть индексированы, как в символьном массиве, многие из String-методов используют индекс (порядковый номер или позицию) символа в строке для выполнения своих операций. Подобно массивам, индекс строки начинается с нуля.
Метод charAt()
Для извлечения одиночного символа из string-объекта вы можете прямо сослаться на индивидуальный символ через метод charAt(). Он имеет следующую общую форму:
char charAt(int where)
где параметр where — индекс (номер) символа, который вы хотите получить. Значение where должно определять позицию искомого символа в строке и не может быть отрицательным. charAt() возвращает символ, находящийся в указанной позиции строки. Например, фрагмент:
char ch;
ch = "abc".charAt(1);
назначает символьное значение "b" переменной ch.
Метод getChars()
Если нужно извлечь больше одного символа, то можно использовать метод getChars(). Он имеет следующую общую форму:
void getChars(int sourceStart, int sourceEnd, char targets[], int targetStart)
Здесь sourceStart указывает индекс начала подстроки; sourceEnd указывает индекс, который на 1 больше индекса конца желательной подстроки. Таким образом подстрока содержит символы в позициях от sourceStart до sourceEnd - 1. Массив, который будет принимать символы, указывается параметром target[]. Позиция в target, начиная с которой будет скопирована подстрока, передается через параметр targetstart. Позаботьтесь, чтобы размер массива target был достаточно большим, чтобы вместить все символы указанной подстроки. Следующая программа демонстрирует getChars():
class GetCharsDemo {
public static void main(String args[]) {
String s = "This is a demo of the getChars method.";
int start = 10;
int end = 14;
char buf[] = new char[end - start];
s.getChars(start, end, buf, 0);
System.out.println(buf);
}
}
Вывод этой программы:
demo
Метод toCharArray()
Если вы хотите преобразовать все символы в объекте типа String в символьный массив, самый простой способ состоит в вызове метода toCharArray(). Он возвращает массив символов всей строки и имеет следующую общую форму:
char[ ] toCharArray()
Эта функция обеспечивает определенные удобства, так как достичь того же результата можно и с помощью метода getChars().
class GetCharsDemo1 {
public static void main(String args[]) {
String s = "This is a demo of the getChars method.";
int start = 10;
int end = 14;
char buf[] = new char[end - start];
s.getChars(start, end, buf, 0);
System.out.println(buf);
char [] mm = s.toCharArray();
for (int i=0; i<s.length(); i++) {
System.out.print(mm[i]+"-");
}
}
}
Результат:
demo
T-h-i-s- -i-s- -a- -d-e-m-o- -o-f- -t-h-e- -g-e-t-C-h-a-r-s- -m-e-t-h-o-d-.-
Сравнение строк
Класс string включает несколько методов, которые сравнивают строки или подстроки внутри строк. Все они рассматриваются в данном разделе.
Методы equals() и equalslgnoreCase()
Чтобы сравнивать две строки на равенство, нужно использовать метод equals(). Он имеет следующую общую форму:
boolean equals(Object str)
где str — string-объект, который сравнивается с вызывающим string-объектом. Метод возвращает значение true, если строки содержат одни и те же символы в одинаковом порядке, иначе возвращается false. Сравнение чувствительно к регистру.
Чтобы выполнить сравнение, которое игнорирует различия в регистре, вызывается метод equalsIgnoreCase(). При сравнении двух строк он предполагает, что символы A—Z и a—z не различаются. Общий формат этого метода:
boolean equalsIgnoreCase(String str)
где str — string-объект, который сравнивается с вызывающим string-объектом. Он тоже возвращает true, если строки содержат одни и те же символы в одном и том же порядке, иначе возвращает false.
Пример, который демонстрируетequals() И IgnoreCase():
// Демонстрирует equals() и equalsIgnoreCase().
class EqualsDemo {
public static void main(String args[]) {
String s1 = "Hello";
String s2 = "Hello";
String s3 = "Good-bye";
String s4 = "HELLO";
System.out.println(s1 + " равно " + s2 + " -> " + s1.equals(s2));
System.out.println(s1 + " равно " + s3 + " -> " + s1.equals(s3));
System.out.println(s1 + " равно " + s4 + " -> " + s1.equals(s4));
System.out.println(s1 + " equalsIgnoreCase " + s4 + " -> " +
s1.equalsIgnoreCase(s4));
}
}
Вывод этой программы:
Hello равно Hello -> true
Hello равно equals Good-bye -> false
Hello равно equals HELLO -> false
Hello equalsIgnoreCase HELLO -> true
Метод regionMatches()
Метод regionMatches () сравнивает некоторую область внутри строчного объекта с другой некоторой областью в другом строчном объекте. Имеется перегруженная форма, которая позволяет игнорировать регистр при таких сравнениях. Общие формы этих двух методов:
boolean regionMatches(int startIndex, String str2,
int str2StartIndex, int numChars)
boolean regionMatches(boolean ignoreCase,
int startIndex, String str2,
int str2StartIndex, int numChars)
Для обеих версий startIndex определяет индекс, с которого область начинается в вызывающем string-объекте. Сравниваемый string-объект указывается параметром str2. Индекс, в котором сравнение начнется внутри str2, определяется параметром str2startindex. Длина сравниваемой подстроки пересылается через numChars. Во второй версии, если ignorecase — true, регистр символов игнорируется. Иначе, регистр учитывается.
Методы startsWith() и endsWith()
В классе String определены две подпрограммы, которые являются специализированными формами метода regionMatches() . Метод startsWith() определяет, начинается ли данный string-объект с указанной строки. Наоборот, метод endswith() определяет, заканчивается ли string-объект указанной строкой. Они имеют следующие общие формы:
boolean startsWith(String str)
boolean endsWith(String str)
где str — проверяемый string-объект. Если строки согласованы, возвращается true, иначе — false. Например,
"Foobar".endsWith("bar")
И
"Foobar".startsWith("Foo")
оба возвращают true.
Вторая форма startsWith() с помощью своего второго параметра (startlndex) позволяет определить начальную точку области сравнения (в вызывающем объекте):
boolean startsWith(String str, int startIndex)
где startIndex определяет индекс символа в вызывающей строке, с которого начинается поиск символов для операции сравнения. Например:
"Foobar".startsWith("bar", 3)
возвращает true (потому что строка первого аргумента вызова точно совпадает с подстрокой "Foobar", начинающейся с четвертой позиции в исходной строке).
Сравнение equals() и операции ==
Важно понять, что метод equals() и оператор == выполняют две различных операции. Как только что было объяснено, метод equals() сравнивает символы внутри string-объекта, а оператор == - две объектные ссылки, чтобы видеть, обращаются ли они к одному и тому же экземпляру (объекту). Следующая программа показывает, что два различных string-объекта могут содержать одни и те же символы, но ссылки на эти объекты не будут оцениваться как равные:
// equals() в сравнении с ==
class EqualsNotEqualTo {
public static void main(String args[]) {
String s1 = "Hello";
String s2 = new String(s1);
System.out.println(s1 + " равен " + s2 + " -> " +s1.equals(s2));
System.out.println(s1 + " == " + s2 + " -> " + (s1 == s2));
}
}
Переменная s1 ссылается на string-экземпляр, созданный строкой "Hello". Объект, на который указывает s2, создается с объектом s1 в качестве инициализатора. Таким образом, содержимое двух string-объектов идентично, но это — разные объекты. Это означает, что s1 и s2 не ссылаются на один и тот же объект и. поэтому, при сравнении с помощью операции == оказываются не равными, как показывает вывод предыдущего примера:
Hello равен Hello -> true
Hello == Hello -> false
Метод compareTo()
Часто, не достаточно просто знать, идентичны ли две строки. Для приложений сортировки нужно знать, какая из них меньше, равна, или больше чем другая. Одна строка считается меньше чем другая, если она расположена перед другой в словарном (упорядоченном по алфавиту) списке. Строка считается больше чем другая, если она расположена после другой в словарном списке. Такое сравнение и выполняет string-метод compareTo(). Он имеет следующую общую форму:
int compareTo(String str)
Здесь str — string-объект, сравниваемый с вызывающим string-объектом. Результат сравнения возвращается (в вызывающую программу) и интерпретируется так:
Меньше нуля: строка вызова — меньше, чем str.
Больше нуля: строка вызова — больше, чем str.
Нуль: две строки равны.
Ниже показан пример программы, которая сортирует массив строк. Программа использует метод compareTo() для упорядочивания строк по алгоритму "пузырьковой сортировки":
// Пузырьковая сортировка строк.
class SortString {
static String arr[] = {
"Now", "is", "the", "time", "for", "all",
"good", "men", "to", "come", "to", "the",
"aid", "of", "their", "country" };
public static void main(String args[]) {
for(int j =0; j < arr.length; j++) {
for(int i = j + 1; i < arr.length; i++) {
if(arr[i].compareTo(arr[j]) < 0) {
String t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
System.out.println(arr[j]);
}
}
}
Вывод этой программы — упорядоченный список слов:
Now
aid
all
come
country
for
good
is
men
of
the
the
their
time
to
to
Как вы видите, compareTo() принимает во внимание символы нижнего и верхнего регистра. Слово "Now" идет перед всеми другими словами, потому что оно начинается с прописной буквы, а это означает, что оно имеет более низкое значение в наборе символов ASCII (где коды прописных букв меньше, чем коды строчных).
Если вы хотите игнорировать различия в регистре при сравнении двух строк, используйте метод compareToIgnoreCase(), формат которого имеет вид:
int compareToIgnoreCase(String str)
Данный метод возвращает те же самые результаты, что и compareTo(), исключая, однако, различия в регистре. Этот метод был добавлен в Java 2. Если вы попробуете подставить его в предыдущую программу (вместо compareTo()), то после выполнения слово "Now" больше не будет первым в списке вывода.
Поиск строк
Класс string предоставляет два метода, которые позволяют выполнять поиск указанного символа или подстроки внутри строки:
indexOf(). Поиск первого вхождения символа или подстроки.
lastindexOf(). Поиск последнего вхождения символа или подстроки.
Эти два метода имеют несколько различных перегруженных вариантов. Во всех случаях методы возвращают индекс того элемента строки, в котором символ или подстрока были найдены. При неудачном поиске возвращается — 1. Для поиска первого вхождения символа используйте
int indexOf(int ch)
Для поиска последнего вхождения символа используйте
int lastlndexOf(int ch)
Здесь ch — разыскиваемый символ.
Для поиска первого или последнего вхождения подстроки используйте
int indexOf(String str) int lastlndexOf(String str)
Здесь str определяет подстроку.
Можно определить начальную точку поиска, применяя следующие формы:
int indexOf(int ch, int startIndex) int lastIndexOf(int ch, int startlndex)
int indexOf(String str, int startIndex)
int lastIndexOf (String str, int startIndex)
Здесь startlndex указывает индекс (номер) символа, с которого начинается
ПОИСК. ДЛЯindexOf () ПОИСК ВЫПОЛНЯетСЯ ОТ СИМВОЛа С ИНДеКСОМ startlndex
до конца строки. Для lastlndexOfо поиск выполняется от символа с индексом startlndex НО нуля.
Следующий пример показывает, как можно использовать различные индексные методы для поиска внутри strings-объекта:
// Демонстрирует indexOf() к lastIndexOf().
class indexOfDemo {
public static void main(String args[]) {
String s = "Now is the time for all good men " +
"to come to the aid of their country.";
System.out.println(s);
System.out.println("indexOf(t) = " + s.indexOf('t'));
System.out.println("lastlndexOf(t) = " + s.lastIndexOf('t'));
System.out.println("indexOf(the) = " + s.indexOf("the"));
System.out.println("lastlndexOf(the) = " + s.lastIndexOf("the"));
System.out.println("indexOf(t, 10) = " + s.indexOf('t', 10));
System.out.println("lastlndexOf(t, 60) = " + s.lastIndexOf('t', 60));
System.out.println("indexOf(the, 10) = " + s.indexOf("the", 10));
System.out.println("lastlndexOf(the, 60) = " + s.lastIndexOf("the", 60));
}
}
Вывод этой программы:
Now is the time for all good men to come to the aid of their country.
indexOf(t) = 7
lastlndexOf(t) = 65
indexOf(the) = 7
lastlndexOf(the) = 55
indexOf(t, 10) =11
lastlndexOf(t, 60) =55
indexOf(the, 10) =44
lastlndexOf (the, 60) =55
Изменение строки
Поскольку string-объекты неизменяемы, всякий раз, когда вы хотите изменить string-объект, нужно или копировать его в stringBuffer, или использовать один из следующих string-методов, которые создадут новую копию строки с вашими модификациями.
Метод substring()
Вы можете извлечь подстроку с помощью метода substring(). Он имеет две формы. Первая:
String substring(int startlndex)
Здесь startIndex специфицирует индекс символа, с которого начнется подстрока. Эта форма возвращает копию подстроки, которая начинается с номера startIndex и простирается до конца строки вызова.
Вторая форма substring() позволяет указывать как начальный, так и конечный индексы подстроки:
String substring(int startlndex, int endlndex)
Здесь startlndex указывает начальный индекс; endindex определяет индекс последнего символа подстроки. Возвращаемая строка содержит все символы от начального до конечного индекса (но не включая символ с конечным индексом).
Следующая программа использует метод substring() для замены всех экземпляров одной подстроки на другую строку:
// Замена подстроки.
class StringReplace {
public static void main(String args[]) {
String org = "This is a test. This is, too.";
String search = "is";
String sub = "was";
String result = "";
int i ;
do { // заменить все совпавшие подстроки
System.out.println(org) ;
i = org.indexOf(search) ;
if(i != -1) {
result = org.substring(0, i);
result = result + sub;
result = result + org.substring(i + search.length());
org = result;
}
}
while(i != -1) ;
}
}
Вывод этой программы:
This is a test. This is, too.
Thwas is a test. This is, too.
Thwas was a test. This is, too.
Thwas was a test. Thwas is, too.
Thwas was a test. Thwas was, too.
Метод concat()
Можно сцеплять две строки, используя метод concat() , с такой сигнатурой:
String concat(String str)
Данный метод создает новый объект, включающий строку вызова с содержимым объекта str, добавленным в конец этой строки, concat () выполняет ту же функцию, что и операция конкатенации +. Например, фрагмент
String s1 = "one";
String s2 = s1.concat("two");
Помещает строку "onetwo" в s2. Он генерирует тот же результат, что следующая последовательность:
String s1 = "one";
String s2 = s1 + "two";
Метод replaced()
Метод replace() заменяет все вхождения одного символа в строке вызова другим символом. Он имеет следующую общую форму:
String replace(char original, char replacement)
Здесь original определяет символ, который будет заменен символом, указанным в replacement. Строка, полученная в результате замены, возвращается в вызывающую программу. Например,
String s = "Hello".replace ('l', 'w');
помешает в s строку "Hewwo".
Метод trim()
Метод trim() возвращает копию строки вызова, из которой удалены любые ведущие и завершающие пробелы. Он имеет следующую общую форму:
String trim()
Пример:
String s = " Hello World ".trim();
Этот оператор помещает в строку s "Hello World".
Метод trim() весьма полезен, когда вы обрабатываете команды пользователя. Например, следующая программа запрашивает у пользователя название штата и затем отображает столицу этого штата. Она использует trim() для удаления любых ведущих и завершающих пробелов, которые, возможно, по неосторожности были введены пользователем.
// Использование trim() для обработки команд.
import java.io.*;
class UseTrim {
public static void main(String args [ ])
throws IOException {
// создать BufferedReader, использующий System.in
BufferedReader br = new
BufferedReader(new InputStreamReader(System.in));
String str;
System.out.println("Enter 'stop' to quit.");
System.out.println("Enter State: ");
do {
str = br.readLine();
str = str.trim(); // удалить пробелы
if(str.equals("Illinois"))
System.out.println("Capital is Springfield."); else if(str.equals("Missouri"))
System.out.println("Capital is Jefferson City."); else if(str.equals("California"))
System.out.println("Capital is Sacramento."); else if(str.equals("Washington"))
System.out.println("Capital is Olympia.");
// ...
} while(!str.equals("stop"));
}
}