Text_en_CA_UNIX.properties




Чтобы выбрать определенный объект ResourceBundle, следует вызвать метод ResourceBundle.getBundle( параметры ). Следующий фрагмент выбирает text объекта ResourceBundle для объекта Locale, который соответствует английскому языку, стране Канаде и платформе UNIX.

Locale currentLocale = new Locale("en", "CA", "UNIX");

ResourceBundle rb =

ResourceBundle.getBundle("text", currentLocale);

Если объект ResourceBundle для заданного объекта Locale не существует, то метод getBundle() извлечет наиболее общий. В случае если общее определение файла ресурсов не задано, то метод getBundle() генерирует исключительную ситуацию MissingResourceException. Чтобы этого не произошло, необходимо обеспечить наличие базового файла ресурсов без суффиксов, а именно: text.properties в отличие от частных случаев вида:

Text_en_US.properties

Text_bel_BY.properties

В файлах свойств информация должна быть организована по принципу:

key1 = value1

key2 = value2

Например: str1 = To be or not to be?

Перечисление всех ключей в виде Enumeration<String> можно получить вызовом метода getKeys(). Конкретное значение по ключу извлекается методом String getString(String key).

В следующем примере в зависимости от выбора пользователя известная фраза будет выведена на одном из трех языков.

// пример # 16: поддержка различных языков: HamletInternational.java

package chapt8;

import java.io.IOException;

import java.io.UnsupportedEncodingException;

import java.util.Locale;

import java.util.ResourceBundle;

 

public class HamletInternational {

public static void main(String[] args) {

String country = "", language = "";

System. out. println("1 - Английский");

System. out. println("2 - Белорусский");

System. out. println("Любой символ - Русский");

char i = 0;

try {

i = (char) System. in. read();

} catch (IOException e1) {

e1.printStackTrace();

}

switch (i) {

case '1':

country = "US";

language = "EN";

break;

case '2':

country = "BY";

language = "BEL";

}

Locale current = new Locale(language, country);

ResourceBundle rb =

ResourceBundle. getBundle ("text", current);

try {

String st = rb.getString("str1");

String s1 =

new String(st.getBytes("ISO-8859-1"), "UTF-8");

System. out. println(s1);

 

st = rb.getString("str2");

String s2 =

new String(st.getBytes("ISO-8859-1"), "UTF-8");

System. out. println(s2);

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

}

}

}

Файл text_en_US.properties содержит следующую информацию:

str1 = To be or not to be?

str2 = This is a question.

Файл text_bel_BY.properties:

str1 = Быць або не быць?

str2 = Вось у чым пытанне.

Файл text.properties:

str1 = Быть или не быть?

str2 = Вот в чём вопрос.

Интернационализация чисел

Стандарты представления дат и чисел в различных странах могут существенно отличаться. Например, в Германии строка "1.234,567" воспринимается как «одна тысяча двести тридцать четыре целых пятьсот шестьдесят семь тысячных», для русских и французов данная строка просто непонятна и не может представлять число.

Чтобы сделать такую информацию конвертируемой в различные региональные стандарты, применяются возможности класса java.text.NumberFormat. Первым делом следует задать или получить текущий объект Locale с шаблонами регионального стандарта и создать с его помощью объект форматирования NumberFormat. Например:

NumberFormat nf =

NumberFormat.getInstance(new Locale("RU"));

с конкретными региональными установками или с установленными по умолчанию для приложения:

NumberFormat.getInstance();

Далее для преобразования строки в число и обратно используются методы Number parse(String source) и String format(double number) соответственно.

В предлагаемом примере производится преобразование строки, содержащей число, в три различных региональных стандарта, а затем одно из чисел преобразуется из одного стандарта в два других.

// пример # 17: региональные представления чисел: DemoNumberFormat.java

package chapt07;

import java.text.*;

import java.util.Locale;

 

public class DemoNumberFormat {

public static void main(String args[]) {

NumberFormat nfGe =

NumberFormat. getInstance (Locale.GERMAN);

NumberFormat nfUs =

NumberFormat. getInstance (Locale.US);

NumberFormat nfFr =

NumberFormat. getInstance (Locale.FRANCE);

 

double iGe=0, iUs=0, iFr =0;

String str = "1.234,567"; //строка, представляющая число

try {

//преобразование строки в германский стандарт

iGe = nfGe.parse(str).doubleValue();

//преобразование строки в американский стандарт

iUs = nfUs.parse(str).doubleValue();

//преобразование строки во французский стандарт

iFr = nfFr.parse(str).doubleValue();

} catch (ParseException e) {

e.printStackTrace();

}

System. out. printf("iGe = %f\niUs = %f\niFr = %f",

iGe, iUs, iFr);

 

//преобразование числа из германского в американский стандарт

String sUs = nfUs.format(iGe);

//преобразование числа из германского во французский стандарт

String sFr = nfFr.format(iGe);

System. out. println("\n" + sUs + "\n" + sFr);

}

}

Результат работы программы:

iGe = 1234,567000

iUs = 1,234000

iFr = 1,000000

1,234.567

1 234,567

Аналогично выполняются переходы от одного регионального стандарта
к другому при отображении денежных сумм.

Интернационализация дат

Учитывая исторически сложившиеся способы отображения даты и времени в различных странах и регионах мира, в языке создан механизм поддержки всех национальных особенностей. Эту задачу решает класс java.text.DateFormat. С его помощью учтены: необходимость представления месяцев и дней недели на национальном языке; специфические последовательности в записи даты и часовых поясов; возможности использования различных календарей.

Процесс получения объекта, отвечающего за обработку регионального стандарта даты, похож на создание объекта, отвечающего за национальные представления чисел, а именно:

DateFormat df = DateFormat.getDateInstance(

DateFormat.MEDIUM, new Locale("BY"));

или по умолчанию:

DateFormat.getDateInstance();

Константа DateFormat.MEDIUM указывает на то, что будут представлены только дата и время без указания часового пояса. Для указания часового пояса используются константы класса DateFormat со значением LONG и FULL. Константа SHORT применяется для сокращенной записи даты, где месяц представлен в виде своего порядкового номера.

Для получения даты в виде строки для заданного региона используется метод String format(Date date) в виде:

String dat = df.format(new Date());

С помощью метода Date parse(String source) можно преобразовать переданную в виде строки дату в объектное представление конкретного регионального формата, например:

String str = "April 3, 2006";

Date d = df.parse(str);

Класс содержит большое количество методов, позволяющих выполнять разнообразные манипуляции с датой и временем.

В качестве примера рассмотрено преобразование заданной даты в различные региональные форматы.

// пример # 18: региональные представления дат: DemoDateFormat.java

package chapt07;

import java.text.DateFormat;

import java.text.ParseException;

import java.util.*;

 

public class DemoDateFormat {

public static void main(String[] args) {

DateFormat df =

DateFormat. getDateInstance (DateFormat.MEDIUM, Locale.US);

Date d = null;

String str = "April 3, 2006";

try {

d = df.parse(str);

System. out. println(d);

} catch (ParseException e) {

e.printStackTrace();

}

df =

DateFormat.getDateInstance(DateFormat.FULL,

new Locale("ru","RU"));

System. out. println(df.format(d));

 

df =

DateFormat.getDateInstance(DateFormat.FULL,Locale.GERMAN);

System. out. println(df.format(d));

 

d = new Date();

//загрузка в объект df текущего времени

df = DateFormat. getTimeInstance ();

//представление и вывод времени в текущем формате дат

System. out. println(df.format(d));

}

}

Результат работы программы:

Mon Apr 03 00:00:00 EEST 2006

3 Апрель 2006 г.

Montag, 3. April 2006

05:45:16

Чтобы получить представление текущей даты во всех возможных региональных стандартах, можно воспользоваться следующим фрагментом кода:

Date d = new Date();

Locale[] locales =

DateFormat.getAvailableLocales();

for (Locale loc: locales) {

DateFormat df =

DateFormat. getDateInstance (DateFormat.FULL, loc);

System.out.println(loc.toString() + "---> "

+ df.format(d));

}

В результате будут выведены две сотни строк, каждая из которых представляет текущую дату в соответствии с региональным стандартом, выводимым перед датой с помощью инструкции loc.toString().

Задания к главе 7

Вариант A

1. В каждом слове текста k-ю букву заменить заданным символом. Если
k больше длины слова, корректировку не выполнять.

2. В русском тексте каждую букву заменить ее порядковым номером
в алфавите. При выводе в одной строке печатать текст с двумя пробелами между буквами, в следующей строке внизу под каждой буквой печатать ее номер.

3. В тексте после буквы Р, если она не последняя в слове, ошибочно напечатана буква А вместо О. Внести исправления в текст.

4. В тексте слова заданной длины заменить указанной подстрокой, длина которой может не совпадать с длиной слова.

5. В тексте после k-го символа вставить заданную подстроку.

6. После каждого слова текста, заканчивающегося заданной под­строкой, вставить указанное слово.

7. В зависимости от признака (0 или 1) в каждой строке текста удалить указанный символ везде, где он встречается, или вставить его после
k-гo символа.

8. Из небольшого текста удалить все символы, кроме пробелов, не являющиеся буквами. Между последовательностями подряд идущих букв оставить хотя бы один пробел.

9. Из текста удалить все слова заданной длины, начинающиеся на согласную букву.

10. Удалить из текста его часть, заключенную между двумя сим­волами, которые вводятся (например, между скобками ‘(’ и ‘)’ или между звездочками ‘*’ и т.п.).

11. В тексте найти все пары слов, из которых одно является об­ращением другого.

12. Найти и напечатать, сколько раз повторяется в тексте каждое слово, которое встречается в нем.

13. В тексте найти и напечатать n символов (и их количество), встречающихся наиболее часто.

14. Найти, каких букв, гласных или согласных, больше в каждом предложении текста.

15. В стихотворении найти количество слов, начинающихся и заканчиваю­щихся гласной буквой.

16. Напечатать без повторения слова текста, у которых первая и последняя буквы совпадают.

17. В тексте найти и напечатать все слова максимальной и все слова минимальной длины.

18. Напечатать квитанцию об оплате телеграммы, если стоимость одного слова задана.

19. В стихотворении найти одинаковые буквы, которые встречаются во всех словах.

20. В тексте найти первую подстроку максимальной длины, не со­держащую букв.

21. В тексте определить все согласные буквы, встречающиеся не более чем в двух словах.

22. Преобразовать текст так, чтобы каждое слово начиналось с заглавной буквы.

23. Подсчитать количество содержащихся в данном тексте знаков препинания.

24. В заданном тексте найти сумму всех встречающихся цифр.

25. Из кода Java удалить все комментарии (//, /*, /**).

26. Дан текст на английском языке. Пусть все слова встречаются четное количество раз, за исключением одного. Определить это слово. При сравнении слов регистр не учитывать.

27. Определить сумму всех целых чисел, встречающихся в заданном тексте.

28. Из английского текста удалить все пробелы, если он разделяет два различных знака препинания и если рядом с ним находится еще один пробел.

29. Строка состоит из упорядоченных чисел от 0 до 100000, записанных подряд без пробелов. Определить, что будет подстрокой от позиции
n до m.

30. Определить количество вхождений заданного слова в текст, игнорируя регистр символов и считая буквы «е», «ё», и «и», «й» одинаковыми.

31. Преобразовать текст так, чтобы только первые буквы каждого предложения были заглавными.

32. Заменить в тексте все шаблоны типа %user%Бендер%/user% на
<a href=”https://www.my.by/search.htm?param=Бендер”>Бендер</a>.

33. В Java код добавить корректные getter и setter-методы для всех полей данного класса, при их отсутствии.

34. Вывести все предложения заданного текста в порядке возрастания
количества слов в каждом из них.

Вариант B

1. В тексте нет слов, начинающихся одинаковыми буквами. Напе­чатать слова текста в таком порядке, чтобы последняя буква каждого слова совпадала с первой буквой последующего слова. Если все слова нельзя напечатать в таком порядке, найти такую цепочку, состоящую из наибольшего количества слов.

2. Найти наибольшее количество предложений текста, в которых есть одинаковые слова.

3. Найти такое слово в первом предложении, которого нет ни в одном из остальных предложений.

4. Во всех вопросительных предложениях текста найти и напеча­тать без повторений слова заданной длины.

5. В каждом предложении текста поменять местами первое слово с последним, не изменяя длины предложения.

6. В предложении из n слов первое слово поставить на место второго, второе – на место третьего, и т.д., (n-1)-е слово – на место n-го, n-е слово поставить на место первого. В исходном и преобразованном предложениях между словами должны быть или один пробел, или знак препинания и один пробел.

7. Текст шифруется по следующему правилу: из исходного текста выби­рается 1, 4, 7, 10-й и т.д. (до конца текста) символы, затем 2, 5, 8, 11-й
и т.д. (до конца текста) символы, затем 3, 6, 9, 12-й и т.д. Зашифровать заданный текст.

8. На основании правила кодирования, описанного в предыдущем примере, расшифровать заданный набор символов.

9. Напечатать слова русского текста в алфавитном порядке по первой
букве. Слова, начинающиеся с новой буквы, печатать с красной строки.

10. Рассортировать слова русского текста по возрастанию доли гласных букв (отношение количества гласных к общему количеству букв в слове).

11. Слова английского текста, начинающиеся с гласных букв, рассортировать в алфавитном порядке по первой согласной букве слова.

12. Все слова английского текста рассортировать по возрастанию количества заданной буквы в слове. Слова с одинаковым коли­чеством расположить в алфавитном порядке.

13. Ввести текст и список слов. Для каждого слова из заданного списка найти, сколько раз оно встречается в тексте, и рассортировать слова по убыванию количества вхождений.

14. Все слова текста рассортировать в порядке убывания их длин, при этом все слова одинаковой длины рассортировать в порядке возрастания
в них количества гласных букв.

15. В тексте исключить подстроку максимальной длины, начинающуюся
и заканчивающуюся заданными символами.

16. Заменить все одинаковые рядом стоящие символы в тексте одним символом.

17. Вывести в заданном тексте все слова, расположив их в алфавитном
порядке.

18. Подсчитать, сколько слов в заданном тексте начинается с прописной
буквы.

19. Подсчитать, сколько раз заданное слово входит в текст.

20. Преобразовать каждое слово в тексте, удалив из него все последующие (предыдущие) вхождения первой (последней) буквы этого слова.

21. Вычеркнуть из текста минимальное количество предложений, так чтобы у любых двух оставшихся предложений было хотя бы одно общее слово.

22. Текст из n2 символов шифруется по следующему правилу:

– все символы текста записываются в квадратную таблицу размерности n в порядке слева направо, сверху вниз;

– таблица поворачивается на 900 по часовой стрелке;

– 1-я строка таблицы меняется местами с последней, 2-я – с предпоследней и т.д.

– 1-й столбец таблицы меняется местами со 2-м, 3-й – с 4-м и т.д.

– зашифрованный текст получается в результате обхода результирующей таблицы по спирали по часовой стрелке, начиная с левого верхнего угла.

Зашифровать текст по указанному правилу.

23. На основании правила кодирования, описанного в предыдущем примере, расшифровать заданный набор символов.

24. Исключить из текста подстроку максимальной длины, начинающуюся и заканчивающуюся одним и тем же символом.

25. Осуществить сжатие английского текста, заменив каждую группу из двух или более рядом стоящих символов, на один символ, за которым следует количество его вхождений в группу. К примеру, строка hellowoooorld должна сжиматься в hel2owo4rld.

26. Распаковать текст, сжатый по правилу из предыдущего задания.

27. Определить, удовлетворяет ли имя файла маске. Маска может содержать символы ‘?’ (произвольный символ) и ‘*’ (произвольное количество произвольных символов).

28. Отсортировать слова в тексте по убыванию количества вхождений заданного символа, а в случае равенства – по алфавиту. Словом считать максимальную группу подряд стоящих не пробельных символов.

29. Буквенная запись телефонных номеров основана на том, что каждой цифре соответствует несколько английских букв: 2 – ABC, 3 – DEF, 4 – GHI, 5 – JKL, 6 – MNO, 7 – PQRS, 8 – TUV, 9 – WXYZ. Написать программу, которая находит в заданном телефонном номере подстроку максимальной длины, соответствующую слову из словаря.

30. В заданном тексте найти подстроку максимальной длины, являющуюся палиндромом, т.е. читающуюся слева направо и справа налево одинаково.

31. Осуществить форматирование заданного текста с выравниванием по левому краю. Программа должна разбивать текст на строки с длиной, не превосходящей заданного количества символов. Если очередное слово не помещается в текущей строке, его необходимо переносить на следующую.

32. Изменить программу из предыдущего примера так, чтобы она осуществляла форматирование с выравниванием по обоим краям. Для этого добавить дополнительные пробелы между словами.

33. Добавить к программе из предыдущего примера возможность переноса слов по слогам. Предполагается, что есть доступ к словарю, в котором для каждого слова указано, как оно разбивается на слоги.

34. Пусть массив содержит миллион символов и необходимо сформировать из них строку путем конкатенации. Определить время работы кода. Как можно ускорить процесс, используя класс StringBuffer?

35. Алгоритм Барроуза – Уиллера для сжатия текстов основывается на пре­образовании Барроуза – Уиллера. Оно производится следующим обра­зом: для слова рассматриваются все его циклические сдвиги, которые затем сортируются в алфавитном порядке, после чего формируется сло­во из последних символов отсортированных циклических сдвигов. К примеру, для слова JAVA циклические сдвиги – это JAVA, AVAJ, VAJA, AJAV. После сортировки по алфавиту получим AJAV, AVAJ, JAVA, VAJA. Значит, результат преобразования – слово VJAA. Реализо­вать программно преобразование Барроуза – Уиллера для данного слова.

36. Восстановить слово по его преобразованию Барроуза – Уиллера. К примеру, получив на вход VJAA, в результате работы программа должна выдать слово JAVA.

Тестовые задания к главе 7

Вопрос 7.1.

Дан код:

public class Quest1 {

public static void main(String[] args) {

String str = new String("java");

int i=1;

char j=3;

System.out.println(str.substring(i,j));

}}

В результате при компиляции и запуске будет выведено:

1) ja;

2) av;

3) ava;

4) jav;

5) ошибка компиляции: заданы некорректные параметры для метода substring().

Вопрос 7.2.

Какую инструкцию следует использовать, чтобы обнаружить позицию буквы v в строке str = "Java"?

1) charAt(2,str);

2) str.charAt(2);

3) str.indexOf('v');

4) indexOf(str,'v');

Вопрос 7.3.

Какие из следующих операций корректны при объявлении?

String s = new String("Java");
String t = new String();
String r = null;

1) r = s + t + r;

2) r = s + t + ’r’;

3) r = s & t & r;

4) r = s && t && r;

Вопрос 7.4.

Дан код:

public class Quest4 {

public static void main(String[] args) {

String str="ava";

char ch=0x74; // 74 - это код символа 'J'

str=ch+str;

System.out.print(str);

}}

В результате при компиляции и запуске будет выведено:

1) 74ava;

2) Java;

3) 0H74ava;

4) ошибка компиляции: недопустимая операция ch+str;

5) ошибка компиляции: недопустимое объявление char ch=0x74;

6) нет правильного ответа.

Вопрос 7.5.

Что будет результатом компиляции и выполнения следующего кода?

public class Quest5 {

public static void main(String[] args) {

StringBuffer s = new StringBuffer("you java");

s.insert(2, "like ");

System.out.print(s);

}}

1) yolike u java;

2) you like java;

3) ylike ou java;

4) you java like;

5) ошибка компиляции;

6) нет правильного ответа.

 

 

 
Глава 8

ИСКЛЮЧЕНИЯ И ОШИБКИ

Иерархия и способы обработки

Исключительные ситуации (исключения) возникают во время выполнения программы, когда возникшая проблема не может быть решена в текущем контексте и невозможно продолжение работы программы. Примерами являются особо «популярные»: попытка индексации вне границ массива, вызов метода на нулевой ссылке или деление на нуль. При возникновении исключения создается объект, описывающий это исключение. Затем текущий ход выполнения приложения останавливается, и включается механизм обработки исключений. При этом ссылка на объект-исключение передается обработчику исключений, который пытается решить возникшую проблему и продолжить выполнение программы. Если в классе используется метод, в котором может возникнуть проверяемая исключительная ситуация, но не предусмотрена ее обработка, то ошибка возникает еще на этапе компиляции. При создании такого метода программист должен включить в код обработку исключений, которые могут генерировать этот метод, или передать обработку исключения на более высокий уровень методу, вызвавшему данный метод.

Throwable
Error
Exception
RuntimeException

Каждой исключительной ситуации поставлен в соответствие некоторый класс. Если подходящего класса не существует, то он может быть создан разработчиком. Все исключения являются наследниками суперкласса Throwable и его подклассов Error и Exception из пакета java.lang.

Рис. 8.1. Иерархия основных классов исключений

Исключительные ситуации типа Error возникают только во время выполнения программы. Такие исключения связаны с серьезными ошибками,
к примеру – переполнение стека, и не подлежат исправлению и не могут обрабатываться приложением. Иерархия классов, наследуемых от класса Error, приведена на рисунке 8.2.

Рис. 8.2. Иерархия классов исключений, наследуемых от класса Error.

На рисунке 8.3 приведена иерархия классов исключений, наследуемых от класса Exception.

Проверяемые исключения должны быть обработаны в методе, который может их генерировать, или включены в throws -список метода для дальнейшей обработки в вызывающих методах. Возможность возникновения проверяемого исключения может быть отслежена на этапе компиляции кода.

Во время выполнения могут генерироваться также исключения, которые могут быть обработаны без ущерба для выполнения программы. Иерархия этих исключений приведена на рисунке 8.4. В отличие от проверяемых исключений, класс RuntimeException и порожденные от него классы относятся к непрове­ряемым исключениям. Компилятор не проверяет, генерирует ли и обрабатывает ли метод эти исключения. Исключения типа RuntimeException автоматически генерируются при возникновении ошибок во время выполнения приложения. Таким образом, нет необходимости в проверке генерации исключения вида:

if(a==null) throw new NullPionterException();

объект класса NullPionterException при возникновении ошибки будет сгенерирован автоматически. Кроме этого, в любом случае нет необходимости в обработке этого исключения непосредственно в методе или в передаче на обработку вызывающему методу с помощью оператора throw. В конце концов исключение будет передано в метод main(), где обрабатывается вызовом метода
printStackTrace(), выдающего данные трассировки.

Рис. 8.3. Иерархия классов проверяемых (checked) исключительных ситуаций

Обычно используется один из трех способов обработки исключений:

· перехват и обработка исключения в блоке try-catch метода;

· объявление исключения в секции throws метода и передача вызывающему методу (для проверяемых исключений);

· использование собственных исключений.

Первый подход можно рассмотреть на следующем примере. При клонировании объекта в определенных ситуациях может возникать исключительная ситуация типа CloneNotSupportedException. Например:

public void changeObject(Student ob) {

try {

Object temp = ob.clone();

//реализация

} catch (CloneNotSupportedException e) {

System. err. print(e);

}

}

Рис. 8.4. Иерархия непроверяемых (unchecked) исключений

При клонировании может возникнуть исключительная ситуация в случае, если переданный объект не поддерживает клонирование (не включен интерфейс Cloneable). В этом случае генерируется соответствующий объект, и управление передается блоку catch, в котором обрабатывается данный тип исключения, иначе блок catch пропускается. Блок try похож на обычный логический блок. Блок catch(){} похож на метод, принимающий в качестве единственного параметра ссылку на объект-исключение и обрабатывающий этот объект.

Второй подход демонстрируется на этом же примере. Метод может генери­ровать исключения, которые сам не обрабатывает, а передает для обработки другим методам, вызывающим данный метод. В этом случае метод должен объявить о таком поведении с помощью ключевого слова throws, чтобы вызывающие методы могли защитить себя от этих исключений. В вызывающих методах должна быть предусмотрена обработка этих исключений. Форма объявления такого метода:

Тип имяМетода(список_аргументов)

throws список_исключений { }

При этом сам таким образом объявляемый метод может содержать блоки try-catch, а может и не содержать их. Например, метод changeObject() можно объявить:

public void changeObject(Student ob)

throws CloneNotSupportedException {

Object temp = ob.clone();

//реализация

}

Ключевое слово throws позволяет разобраться с исключениями методов «чужих» классов, код которых отсутствует. Обрабатывать исключение при этом будет метод, вызывающий changeObject():

public void load(Student stud) {

try {

changeObject(stud);

} catch (CloneNotSupportedException e) {

String error = e.toString();

System. err. println(error);

}

}

Создание собственных исключений будет рассмотрено позже в этой главе.

Если в блоке try может быть сгенеририровано в разных участках кода несколько типов исключений, то необходимо наличие нескольких блоков catch, если только блок catch не обрабатывает все типы исключений.

/* пример # 1: обработка двух типов исключений: TwoException.java */

package chapt08;

public class TwoException {

public static void main(String[] args) {

try {

int a = (int)(Math. random () * 2);

System. out. println("a = " + a);

int c[] = { 1/a };

c[a] = 71;

} catch (ArithmeticException e) {

System. err. println("деление на 0" + e);

} catch (ArrayIndexOutOfBoundsException e) {

System. err. println(

"превышение границ массива: " + e);

} //последний catch

System. out. println("после блока try-catch");

}

}

Исключение "деление на 0" возникнет при инициализации элемента массива а=0. В противном случае (при а=1) генерируется исключение "превышение границ массива" при попытке присвоить значение второму элементу массива с[], который содержит только один элемент. Однако пример, приведенный выше, носит чисто демонстративный характер и не является образцом хорошего кода, так как в этой ситуации можно было обойтись простой проверкой аргументов на допустиые значения перед выполнением операций. К тому же генерация и обработка исключения – операция значительно более ресурсоемкая, чем вызов оператора if для проверки аргумента. Исключения должны применяться только для обработки исключительных ситуаций, и если существует возможность обойтись без них, то следует так и поступить.

Подклассы исключений в блоках catch должны следовать перед любым из их суперклассов, иначе суперкласс будет перехватывать эти исключения. Например:

try { /*код, который может вызвать исключение*/

} catch (RuntimeException e) { /* суперкласс RuntimeException

перехватит объекты всех своих подклассов */

} catch (ArithmeticException e) {} /* не может быть вызван,

поэтому возникает ошибка компиляции */

Операторы try можно вкладывать друг в друга. Если у оператора try низкого уровня нет раздела catch, соответствующего возникшему исключению, поиск будет развернут на одну ступень выше, и будут проверены разделы catch внешнего оператора try.

/* пример # 2: вложенные блоки try-catch: MultiTryCatch.java */

package chapt08;

public class MultiTryCatch {

public static void main(String[] args) {

try { // внешний блок

int a = (int) (Math. random () * 2) - 1;

System. out. println("a = " + a);

try { // внутренний блок

int b = 1/a;

StringBuffer sb = new StringBuffer(a);

} catch (NegativeArraySizeException e) {

System. err. println(

"недопустимый размер буфера: " + e);

}

} catch (ArithmeticException e) {

System. err. println("деление на 0" + e);

}

}

}

В результате запуска приложения при a=0 будет сгенерировано исключение ArithmeticException,а подходящий для его обработки блок try–catch является внешним по отношению к месту генерации исключения. Этот блок и будет задействован для обработки возникшей исключительной ситуации.

Третий подход к обработке исключений будет рассмотрен ниже на примере создания пользовательских исключений.

Оператор throw

В программировании часто возникают ситуации, когда программисту необходимо самому инициировать генерацию исключения для указания, напри­мер, на заведомо ошибочный результат выполнения операции, на некорректные значения параметра метода и др. Исключительную ситуацию можно создать с помощью оператора throw, если объект-исключение уже существует, или инициализировать его прямо после этого оператора. Оператор throw используется для генерации исключения. Для этого может быть использован объект класса Throwable или объект его подкласса, а также ссылки на них. Общая форма записи инструкции throw, генерирующей исключение:

throw объектThrowable;

Объект-исключение может уже существовать или создаваться с помощью оператора new:

throw new IOException();

При достижении оператора throw выполнение кода прекращается. Ближайший блок try проверяется на наличие соответствующего обработчика catch. Если он существует, управление передается ему, иначе проверяется следующий из вложенных операторов try. Инициализация объекта-исключения без оператора throw никакой исключительной ситуации не вызовет.

Ниже приведен пример, в котором сначала создается объект-исключение, затем оператор throw генерирует исключение, обрабатываемое в разделе catch,
в котором генерируется другое исключение.

/* пример # 3: генерация исключений: ThrowGeneration.java */

package chapt08;

import java.io.File;

public class ThrowGeneration {

public static void connectFile(File file) {

if (file == null ||!file.exists())

throw new IllegalArgumentException(); /*генерация

исключения */

//…

}

public static void main(String[] args) {

File f = new File("demo.txt");

// File f = null;

try {

connectFile (f);

} catch (IllegalArgumentException e) {

System. err. print("обработка unchecked-"

+ " исключения вне метода: " + e);

}

}

Вызываемый метод connectFile() может (при отсутствии файла на диске или при аргументе null) генерировать исключение, перехватываемое обработчиком. В результате этого объект непроверяемого исключения IllegalArgumentException, как подкласса класса RuntimeException, передается обработчику исключений в методе main().

В случае генерации проверяемого исключения компилятор требует обра­ботки исключения в методе или отказа от нее с помощью инструкции throws.

Если метод генерирует исключение с помощью оператора throw и при этом блок catch в методе отсутствует, то для передачи обработки исключения вызывающему методу тип проверяемого (checked) класса исключений должен быть указан в операторе throws при объявлении метода. Для исключений, являющихся подклассами класса RuntimeException (unchecked) и используемых для отображения программных ошибок, при выполнении приложения throws в объявлении должен отсутствовать.

Ключевое слово finally

Возможна ситуация, при которой нужно выполнить некоторые действия по завершению программы (закрыть поток, освободить соединение с базой данных) вне зависимости от того, произошло исключение или нет. В этом случае используется блок finally, который выполняется после инструкций try или catch. Например:

try { /*код, который может вызвать исключение*/ }

catch (Exception1 e1) { /*обработка исключения е1*/ } //необязателен

catch (Exception2 e2) { /*обработка исключения е2*/ } //необязателен

finally { /*выполняется или после try, или после catch */ }

Каждому разделу try должен соответствовать по крайней мере один раздел catch или блок finally. Блок finally часто используется для закрытия файлов и освобождения других ресурсов, захваченных для временного использования в начале выполнения метода. Код блока выполняется перед выходом из метода даже в том случае, если перед ним были выполнены инструкции вида return, break, continue. Приведем пример:

/* пример # 4: выполнение блоков finally: StudentFinally.java */

package chapt08;

 

public class StudentFinally {

private static int age;

public static void setAge(int age) {

try {

//реализация

if (age <= 0)

throw new RuntimeException("не бывает");

} finally {

System. out. print("освобождение ресурсов");

//реализация

}

System. out. print("конец метода");

}

public static int getAgeWoman() {

try {

return age - 3;

} finally {

return age;

}

}

public static void main(String[] args) {

try {

setAge (23);

setAge (-5);

} catch (RuntimeException e) {

e.printStackTrace();

}

System. out. print(getAgeWoman ());

}

}

В методе setAge() из-за генерации исключения происходит преждевременный выход из блока try, но до выхода из функции выполняется раздел finally. Метод getAgeWoman() завершает работу выполнением стоящего
в блоке try оператора return, но и при этом перед выходом из метода выполняется код блока finally.

Собственные исключения

Разработчик может создать собственное исключение как подкласс класса Exception и затем использовать его при обработке ситуаций, не являющихся исключениями с точки зрения языка, но нарушающих логику вещей. Например, появление объектов типа Human (Человек) с отрицательным значением поля age (возраст).

/* пример # 5: метод, вызывающий исключение, созданное программистом:

RunnerLogic.java */

package chapt08;

publ



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: