Кен Арнольд Джеймс Гослинг
Вид материала | Документы |
Содержание7.5. Когда применяются исключения Глава 8СТРОКИ 8.1. Основные операции со строками String(String value) |
- Джеймс трефил, 41001.36kb.
- Джеймс А. Дискретная математика и комбинаторика [Текст] / Джеймс А. Андерсон, 42.79kb.
- Человеческая способность эти ценности производить и использовать; является важнейшей, 110.76kb.
- Джеймс блиш города в полете 1-4 триумф времени вернись домой, землянин жизнь ради звезд, 10495.38kb.
- Джеймс Н. Фрей. Как написать гениальный роман, 2872.12kb.
- Дп «авто интернешнл» Київ, вул. Урицького, 1а Тел. (044) 20-60-333 Факс. (044) 20-60-343, 82.44kb.
- Тема Кол-во страниц, 26.85kb.
- Тема Кол-во страниц, 56.3kb.
- Тема Кол-во страниц, 20.7kb.
- Арнольд И. В. Стилистика современного английского языка, 20.42kb.
7.5. Когда применяются исключения
В начале этой главы мы воспользовались выражением “неожиданное ошибочное состояние”, чтобы описать момент возбуждения исключения. Исключения не предназначаются для простых, предсказуемых ситуаций. Например, достижение конца входного потока является заранее предсказуемым, так что проверка на “исчерпание” потока является частью ожидаемого поведения метода. Код возврата, сигнализирующий о конце ввода, и проверка его при вызове также выглядят вполне разумно — к тому же такую конструкцию оказывается проще понять. Сравним типичный цикл, в котором используется флаг возврата
while ((token = stream.next()) != Stream.END)
process(token);
stream.close();
с другим циклом, в котором о достижении конца ввода сигнализирует исключение:
try {
for (;;) {
process(stream.next());
}
} catch (StreamEndException e) {
stream.close();
}
В первом случае логика выполнения программы оказывается прямолинейной и понятной. Цикл выполняется до тех пор, пока не будет достигнут конец входного потока, после чего поток закрывается. Во втором случае цикл выглядит так, словно он выполняется бесконечно. Если не знать о том, что о конце ввода сигнализирует StreamEndException, то становится непонятно, когда же происходит выход из цикла. Впрочем, даже если вы догадываетесь о существовании StreamEndException, то факт завершения цикла оказывается вынесенным из его тела (for) во внешний блок try, что затрудняет понимание происходящего.
Встречаются ситуации, в которых невозможно найти приемлемый код возврата. Например, в классе, представляющем поток значений типа double, может содержаться любое допустимое double, поэтому числовой маркер конца потока невозможен. Более разумный подход предусматривает специальный метод eof для проверки конца потока, который должен выполняться перед каждой операцией чтения:
while (!stream.eof())
process(stream.nextDouble());
stream.close();
С другой стороны, попытка чтения после достижения конца файла оказывается непредсказуемой. Она свидетельствует о том, что программа не заметила конца входного потока и теперь пытается сделать что-то такое, чего делать ни в коем случае не следует. Перед нами — отличная возможность применить исключение ReadPastEndException. Подобные действия выходят за границы ожидаемого поведение класса-потока, так что возбуждение исключения в данном случае оказывается вполне уместным.
Решить, какая ситуация является предсказуемой, а какая — нет, порой бывает нелегко. Главное — не злоупотреблять исключениями для сообщений о предсказуемых ситуациях.
Упражнение 7.2
Как, по вашему мнению, программа должна сообщать программисту о следующих ситуациях:
- Программа пытается присвоить отрицательное значение вместимости машины в объекте PassengerVehicle.
- В файле конфигурации, используемом для задания начального состояния объекта, обнаружена синтаксическая ошибка.
- Метод, который ищет в строковом массиве указанное программистом слово, не может найти ни одного экземпляра такого слова.
- Файл, передаваемый методу open, не существует.
- Файл, передаваемый методу open, существует, но система безопасности не разрешает пользователю работать с ним.
- При попытке установить сетевое соединение с удаленным процессом-сервером не удается связаться с удаленным компьютером.
- Во время взаимодействия с удаленным процессом-сервером прерывается сетевое соединение.
Глава 8
СТРОКИ
Что толку в хорошей цитате, если ее нельзя изменить?
Доктор Who, The Two Doctors
Строки в Java являются стандартными объектами со встроенной языковой поддержкой. Нам уже встречалось множество примеров того, как строковые объекты создаются на основе литералов; кроме того, мы видели, как операторы + и += применяются для конкатенации и создания новых строк. Тем не менее функции класса String этим не ограничиваются. Объекты String доступны только для чтения, поэтому в Java также имеется класс StringBuffer для изменяемых строк. В этой главе описаны классы String и StringBuffer, а также преобразование строк в другие типы — например, целый или логический.
8.1. Основные операции со строками
Класс String позволяет работать со строками, доступными только для чтения, и поддерживает операции с ними. Строки могут создаваться неявным образом при помощи заключенной в кавычки последовательности символов (например, “GrцЯe”) или за счет выполнения оператора + или += над двумя объектами String.
Кроме того, допускается и явное построение объектов String оператором new. В классе String предусмотрены следующие конструкторы:
public String()
Конструирует новый объект String, значение которого равно “”.
public String(String value)
Конструирует новый объект String, являющийся копией заданного.
При работе с объектами String используются два базовых метода — length и charAt. Метод length возвращает количество символов в строке, а метод charAt — символ в заданной позиции. Приведенный ниже цикл подсчитывает количество вхождений каждого из символов в строку:
for (int i = 0; i << str.length(); i++)
counts[str.charAt(i)]++;
При попытке обратиться в методе charAt или любом другом методе String к позиции, номер которой отрицателен либо превышает length()-1, возбуждается исключение IndexOutOfBoundsException. Подобные неверные обращения обычно обусловлены наличием ошибок в программе.
Кроме того, имеются простые методы для поиска в строке первого или последнего вхождения конкретного символа или подстроки. Следующий метод возвращает количество символов между первым и последним вхождением заданного символа в строке:
static int countBetween(String str, char ch) {
int begPos = str.indexOf(ch);
if (begPos << 0) // не входит
return -1;
int endPos = str.lastIndexOf(ch);
return endPos - begPos - 1;
}
Данный метод находит первую и последнюю позицию символа ch в строке str. Если символ входит в строку менее двух раз, метод возвращает –1. Разность между номерами позиций превышает на единицу количество символов между ними (количество символов между позициями 2 и 3 равно 0).
Существует несколько перегруженных вариантов метода indexOf для поиска в прямом направлении и метода lastIndexOf — для поиска в обратном направлении. Каждый из методов возвращает номер найденной позиции или –1, если поиск оказался безуспешным:
Метод | Возвращаемое значение |
indexOf(char ch) | первая позиция ch |
indexOf(char ch, int start) | первая позиция ch start |
indexOf(String str) | первая позиция str |
indexOf(String str, int start) | первая позиция str start |
lastIndexOf(char ch) | последняя позиция ch |
lastIndexOf(char ch, int start) | последняя позиция ch start |
lastIndexOf(String str) | последняя позиция str |
lastIndexOf(String str, int start) | последняя позиция str start |
Упражнение 8.1
Напишите метод, который подсчитывает количество вхождений данного символа в строку.
Упражнение 8.2
Напишите метод, который подсчитывает количество вхождений некоторой подстроки в данную строку.