Экземпляром какого класса является поле system err
Перейти к содержимому

Экземпляром какого класса является поле system err

  • автор:

Обработка ошибок и исключения

2. Коды возврата. Основная идея — в случае ошибки возвращать специальное значение, которое не может быть корректным. Например, если в методе есть операция деления, то придется проверять делитель на равенство нулю. Также проверим корректность аргументов a и b :

Double f(Double a, Double b) < if ((a == null) || (b == null)) < return null; > //. if (Math.abs(b) < EPS) < return null; > else < return a / b; > >

При вызове метода необходимо проверить возвращаемое значение:

Double d = f(a, b); if (d != null) < //. > else < //. >

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

3.Использовать флаг ошибки: при возникновении ошибки устанавливать флаг в соответствующее значение:

boolean error; Double f(Double a, Double b) < if ((a == null) || (b == null)) < error = true; return null; > //. if (Math.abs(b) < EPS) < error = true; return b; > else < return a / b; > >
error = false; Double d = f(a, b); if (error) < //. > else < //. >

Минусы такого подхода аналогичны минусам использования кодов возврата.

4.Можно вызвать метод обработки ошибки и возвращать то, что вернет этот метод.

Double f(Double a, Double b) < if ((a == null) || (b == null)) < return nullPointer(); > //. if (Math.abs(b) < EPS) < return divisionByZero(); > else < return a / b; > >

Но в таком случае не всегда возможно проверить корректность результата вызова основного метода.

5.В случае ошибки просто закрыть программу.

if (Math.abs(b) < EPS) < System.exit(0); return this; >

Это приведет к потере данных, также невозможно понять, в каком месте возникла ошибка.

Исключения

В Java возможна обработка ошибок с помощью исключений:

Double f(Double a, Double b) < if ((a == null) || (b == null)) < throw new IllegalArgumentException("arguments of f() are null"); > //. return a / b; >

Проверять b на равенство нулю уже нет необходимости, так как при делении на ноль метод бросит непроверяемое исключение ArithmeticException .

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

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

Таким образом, механизм обработки исключений содержит следующие операции:

  1. Создание объекта-исключения.
  2. Заполнение stack trace’а этого исключения.
  3. Stack unwinding (раскрутка стека) в поисках нужного обработчика.

Классификация исключений

Класс Java Throwable описывает все, что может быть брошено как исключение. Наследеники Throwable — Exception и Error — основные типы исключений. Также RuntimeException , унаследованный от Exception , является существенным классом.

Иерархия стандартных исключений

Проверяемые исключения

Наследники класса Exception (кроме наслеников RuntimeException ) являются проверяемыми исключениями(checked exception). Как правило, это ошибки, возникшие по вине внешних обстоятельств или пользователя приложения – неправильно указали имя файла, например. Эти исключения должны обрабатываться в ходе работы программы, поэтому компилятор проверяет наличие обработчика или явного описания тех типов исключений, которые могут быть сгенерированы некоторым методом.

Все исключения, кроме классов Error и RuntimeException и их наследников, являются проверяемыми.

Error

Класс Error и его подклассы предназначены для системных ошибок. Свои собственные классы-наследники для Error писать (за очень редкими исключениями) не нужно. Как правило, это действительно фатальные ошибки, пытаться обработать которые довольно бессмысленно (например OutOfMemoryError ).

RuntimeException

Эти исключения обычно возникают в результате ошибок программирования, такие как ошибки разработчика или неверное использование интерфейса приложения. Например, в случае выхода за границы массива метод бросит OutOfBoundsException . Такие ошибки могут быть в любом месте программы, поэтому компилятор не требует указывать runtime исключения в объявлении метода. Теоретически приложение может поймать это исключение, но разумнее исправить ошибку.

Обработка исключений

Чтобы сгенерировать исключение используется ключевое слово throw . Как и любой объект в Java, исключения создаются с помощью new .

if (t == null) < throw new NullPointerException("t = null"); >

Есть два стандартных конструктора для всех исключений: первый — конструктор по умолчанию, второй принимает строковый аргумент, поэтому можно поместить подходящую информацию в исключение.

Возможна ситуация, когда одно исключение становится причиной другого. Для этого существует механизм exception chaining. Практически у каждого класса исключения есть конструктор, принимающий в качестве параметра Throwable – причину исключительной ситуации. Если же такого конструктора нет, то у Throwable есть метод initCause(Throwable) , который можно вызвать один раз, и передать ему исключение-причину.

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

void f() throws InterruptedException, IOException < //. 

try-catch-finally

Код, который может бросить исключения оборачивается в try -блок, после которого идут блоки catch и finally (Один из них может быть опущен).

try < // Код, который может сгенерировать исключение >

Сразу после блока проверки следуют обработчики исключений, которые объявляются ключевым словом catch.

try < // Код, который может сгенерировать исключение > catch(Type1 id1) < // Обработка исключения Type1 > catch(Type2 id2) < // Обработка исключения Type2 >

Сatch -блоки обрабатывают исключения, указанные в качестве аргумента. Тип аргумента должен быть классом, унаследованного от Throwable , или самим Throwable . Блок catch выполняется, если тип брошенного исключения является наследником типа аргумента и если это исключение не было обработано предыдущими блоками.

Код из блока finally выполнится в любом случае: при нормальном выходе из try , после обработки исключения или при выходе по команде return .

NB: Если JVM выйдет во время выполнения кода из try или catch , то finally -блок может не выполниться. Также, например, если поток выполняющий try или catch код остановлен, то блок finally может не выполниться, даже если приложение продолжает работать.

Блок finally удобен для закрытия файлов и освобождения любых других ресурсов. Код в блоке finally должен быть максимально простым. Если внутри блока finally будет брошено какое-либо исключение или просто встретится оператор return , брошенное в блоке try исключение (если таковое было брошено) будет забыто.

import java.io.IOException; public class ExceptionTest < public static void main(String[] args) < try < try < throw new Exception("a"); > finally < throw new IOException("b"); > > catch (IOException ex) < System.err.println(ex.getMessage()); > catch (Exception ex) < System.err.println(ex.getMessage()); > > >

После того, как было брошено первое исключение — new Exception(«a») — будет выполнен блок finally , в котором будет брошено исключение new IOException(«b») , именно оно будет поймано и обработано. Результатом его выполнения будет вывод в консоль b . Исходное исключение теряется.

Обработка исключений, вызвавших завершение потока

При использовании нескольких потоков бывают ситуации, когда поток завершается из-за исключения. Для того, чтобы определить с каким именно, начиная с версии Java 5 существует интерфейс Thread.UncaughtExceptionHandler . Его реализацию можно установить нужному потоку с помощью метода setUncaughtExceptionHandler . Можно также установить обработчик по умолчанию с помощью статического метода Thread.setDefaultUncaughtExceptionHandler .

Интерфейс Thread.UncaughtExceptionHandler имеет единственный метод uncaughtException(Thread t, Throwable e) , в который передается экземпляр потока, завершившегося исключением, и экземпляр самого исключения. Когда поток завершается из-за непойманного исключения, JVM запрашивает у потока UncaughtExceptionHandler , используя метод Thread.getUncaughtExceptionHandler() , и вызвает метод обработчика – uncaughtException(Thread t, Throwable e) . Все исключения, брошенные этим методом, игнорируются JVM.

Информация об исключениях

  • getMessage() . Этот метод возвращает строку, которая была первым параметром при создании исключения;
  • getCause() возвращает исключение, которое стало причиной текущего исключения;
  • printStackTrace() печатает stack trace, который содержит информацию, с помощью которой можно определить причину исключения и место, где оно было брошено.
Exception in thread "main" java.lang.IllegalStateException: A book has a null property at com.example.myproject.Author.getBookIds(Author.java:38) at com.example.myproject.Bootstrap.main(Bootstrap.java:14) Caused by: java.lang.NullPointerException at com.example.myproject.Book.getId(Book.java:22) at com.example.myproject.Author.getBookIds(Author.java:35)

Все методы выводятся в обратном порядке вызовов. В примере исключение IllegalStateException было брошено в методе getBookIds , который был вызван в main . «Caused by» означает, что исключение NullPointerException является причиной IllegalStateException .

Разработка исключений

Чтобы определить собственное проверяемое исключение, необходимо создать наследника класса java.lang.Exception . Желательно, чтобы у исключения был конструкор, которому можно передать сообщение:

public class FooException extends Exception < public FooException() < super(); > public FooException(String message) < super(message); > public FooException(String message, Throwable cause) < super(message, cause); > public FooException(Throwable cause) < super(cause); > >

Исключения в Java7

  • обработка нескольких типов исключений в одном catch -блоке:

catch (IOException | SQLException ex)

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

Байт-код, сгенерированный компиляцией такого catch -блока будет короче, чем код нескольких catch -блоков.

  • Try с ресурсами позволяет прямо в try -блоке объявлять необходимые ресурсы, которые по завершению блока будут корректно закрыты (с помощью метода close() ). Любой объект реализующий java.lang.AutoCloseable может быть использован как ресурс.
static String readFirstLineFromFile(String path) throws IOException < try (BufferedReader br = new BufferedReader(new FileReader(path))) < return br.readLine(); > >

В приведенном примере в качестве ресурса использутся объект класса BufferedReader , который будет закрыт вне зависимосити от того, как выполнится try -блок.

Можно объявлять несколько ресурсов, разделяя их точкой с запятой:

public static void viewTable(Connection con) throws SQLException < String query = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES"; try (Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(query)) < //Work with Statement and ResultSet > catch (SQLException e) < e.printStackTrace; >>

Во время закрытия ресурсов тоже может быть брошено исключение. В try-with-resources добавленна возможность хранения «подавленных» исключений, и брошенное try -блоком исключение имеет больший приоритет, чем исключения получившиеся во время закрытия. Получить последние можно вызовом метода getSuppressed() от исключения брошенного try -блоком.

  • Перебрасывание исключений с улучшенной проверкой соответствия типов.

Компилятор Java SE 7 тщательнее анализирует перебрасываемые исключения. Рассмотрим следующий пример:

static class FirstException extends Exception < >static class SecondException extends Exception < >public void rethrowException(String exceptionName) throws Exception < try < if ("First".equals(exceptionName)) < throw new FirstException(); > else < throw new SecondException(); > > catch (Exception ex) < throw e; > >

В примере try -блок может бросить либо FirstException , либо SecondException . В версиях до Java SE 7 невозможно указать эти исключения в декларации метода, потому что catch -блок перебрасывает исключение ex , тип которого — Exception .

В Java SE 7 вы можете указать, что метод rethrowException бросает только FirstException и SecondException . Компилятор определит, что исключение Exception ex могло возникнуть только в try -блоке, в котором может быть брошено FirstException или SecondException . Даже если тип параметра catch — Exception , компилятор определит, что это экземпляр либо FirstException , либо SecondException :

public void rethrowException(String exceptionName) throws FirstException, SecondException < try < // . > catch (Exception e) < throw e; > >

Если FirstException и SecondException не являются наследниками Exception , то необходимо указать и Exception в объявлении метода.

Примеры исключений

  • любая операция может бросить VirtualMachineError . Как правило это происходит в результате системных сбоев.
  • OutOfMemoryError . Приложение может бросить это исключение, если, например, не хватает места в куче, или не хватает памяти для того, чтобы создать стек нового потока.
  • IllegalArgumentException используется для того, чтобы избежать передачи некорректных значений аргументов. Например:
public void f(Object a) < if (a == null) < throw new IllegalArgumentException("a must not be null"); > >
  • IllegalStateException возникает в результате некорректного состояния объекта. Например, использование объекта перед тем как он будет инициализирован.

Гарантии безопасности

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

  • Отсутствие гарантий (no exceptional safety). Если было брошено исключение, то не гарантируется, что все ресурсы будут корректно закрыты и что объекты, методы которых бросили исключения, могут в дальнейшем использоваться. Пользователю придется пересоздавать все необходимые объекты и он не может быть уверен в том, что может переиспозовать те же самые ресурсы.
  • Отсутствие утечек (no-leak guarantee). Объект, даже если какой-нибудь его метод бросает исключение, освобождает все ресурсы или предоставляет способ сделать это.
  • Слабые гарантии (weak exceptional safety). Если объект бросил исключение, то он находится в корректном состоянии, и все инварианты сохранены. Рассмотрим пример:
class Interval < //invariant: left double left; double right; //. >

Если будет брошено исключение в этом классе, то тогда гарантируется, что ивариант «левая граница интервала меньше правой» сохранится, но значения left и right могли измениться.

  • Сильные гарантии (strong exceptional safety). Если при выполнении операции возникает исключение, то это не должно оказать какого-либо влияния на состояние приложения. Состояние объектов должно быть таким же как и до вызовов методов.
  • Гарантия отсутствия исключений (no throw guarantee). Ни при каких обстоятельствах метод не должен генерировать исключения. В Java это невозможно, например, из-за того, что VirtualMachineError может произойти в любом месте, и это никак не зависит от кода. Кроме того, эту гарантию практически невозможно обеспечить в общем случае.

Источники

  • Обработка ошибок и исключения — Сайт Георгия Корнеева
  • Лекция Георгия Корнеева — Лекториум
  • The Java Tutorials. Lesson: Exceptions
  • Обработка исключений — Википедия
  • Throwable (Java Platform SE 7 ) — Oracle Documentation
  • try/catch/finally и исключения — www.skipy.ru

Java | Вопросы с ответами

2. Дан код:
public class Quest4 public static void main(String[] args) byte b[] = new byte[80];
for (int i=0; i System.out.print(“Ok”);
>
>
Результатом компиляции запуска будет?
>> ошибка компиляции, так как метод read() может порождать исключительную ситуацию типа IOException.

3. Программы Java категория Приложение (application)?
>> аналог “обычной” прикладной программы.

4. Программы Java категория Апплет (applet)?
>> специализированная программа с ограниченными возможностями, работающая в окне WWW-документа под управлением браузера.

5. Программы Java категория Сервлет (servlet)?
>> специализированная программа с ограниченными возможностями, работающая в WWW на стороне сервера. Используется преимущественно в рамках технологии JSP для программирования WWW-документов со стороны сервера.

6. Программы Java категория Серверное приложение (Enterprise application)?
>> предназначено для многократного использования на стороне сервера.

7. Программы Java категория Библиотека (Java Class Library)?
>> библиотека классов, либо NetBeansModule – модуль платформы NetBeans) – предназначена для многократного использования программами Java.

8. Какие из следующих строк скомпилируются без ошибки?
>> int i = 32565;
— float f = 7.0;
— char c = «z»;
— byte b = 255;
— boolean n = null;

9. Какие из следующих строк скомпилируются без ошибки?
>> int j = ’ъ’;
— float f = 7.0;
— char c = «z»;
— byte b = 255;
— boolean n = null;

10. Какие варианты записи оператора условного перехода корректны?
>> if (i
— if (i — if i
— if [i — if then System.out.print(«-6-«);

12. Какие из следующих идентификаторов являются корректными?
>> _int;
— 2int;
— int_#;
— #int
— _#int

13. Назначение утилиты javac?
>> Компилятор в режиме командной строки для программ, написанных на языке Java.

14. Назначение утилиты java?
>> Утилита для запуска в режиме командной строки откомпилированных программ-приложений.

15. Назначение утилиты appletviewer?
>> Утилита для запуска на исполнение и отладку апплетов без браузера. При этом не гарантируется работоспособность отлаженного апплета в браузере.

16. Назначение утилиты jdb?
>> Отладчик программ, написанных на языке Java.

17. Назначение утилиты javadoc?
>> Генератор документации по классом на основе комментариев, начинающихся с /**.

18. Назначение утилиты jar?
>> Создание и управление Java-архивами jar.

19. Назначение утилиты javah?
>> Генератор заголовочных файлов C/C++ для подключения к программам Java внешних библиотек C/C++ на основе интерфейса JNI.

20. Назначение утилиты javap?
>> Дизассемблер классов.

21. Назначение утилиты extcheck?
>> Утилита для обнаружения конфликтов между файлами архивов jar.

22. Назначение утилиты native2ascii?
>> Утилита для конвертации в режиме командной строки параметра, передаваемого в виде текста на национальном алфавите, в последовательность символов UNICODE.

23. Управляющая последовательность: \a ?
>> звонок.

24. Управляющая последовательность: \b ?
>> возврат на один символ назад.

25. Управляющая последовательность: \f ?
>> перевод на новую страницу.

26. Управляющая последовательность: \n ?
>> перевод на новую строку.

27. Управляющая последовательность: \r ?
>> возврат к началу строки.

28. Управляющая последовательность: \t ?
>> горизонтальная табуляция.

29. Управляющая последовательность: \v ?
>> вертикальная табуляция.

30. Управляющая последовательность: \’ ?
>> кавычка.

31. Управляющая последовательность: \” ?
>> двойные кавычки.

32. Управляющая последовательность: \\ ?
>> обратная косая черта.

33. Управляющая последовательность: \u ?
>> начало кодировки символа Unicode.

34. Оператор ~ ?
>> Оператор побитового дополнения (побитовое “не”).

35. Оператор ^ ?
>> Оператор “исключающее или” (XOR).

36. Оператор & ?
>> Оператор “побитовое и” (AND).

37. Оператор | ?
>> Оператор “побитовое или” (OR).

38. Оператор ! ?
>> Оператор “НЕ”.

39. Оператор && ?
>> Оператор “логическое И” (AND).

40. Оператор || ?
>> Оператор “ логическое ИЛИ” (OR).

41. Оператор >> Оператор левого побитового сдвига.

42. Оператор >>> ?
>> Оператор беззнакового правого побитового сдвига.

43. Оператор >> ?
>> Оператор правого побитового сдвига с сохранением знака отрицательного числа.

44. Для чего предназначен пакет java.applet?
>> Классы, необходимые для создания аплетов.

45. Для чего предназначен пакет java.awt?
>> Графический пользовательский интерфейс на базе AbstractWindowsToolkit.

46. Для чего предназначен пакет java.awt.color?
>> Пространства цветов для AWT.

47. Для чего предназначен пакет java.awt.datatransfer?
>> Передача данных внутри программы и между программами.

48. Для чего предназначен пакет java.awt.dnd?
>> Поддержка технологии drag-and-drop.

49. Для чего предназначен пакет java.awt.event?
>> Обработка событий AWT.

50. Для чего предназначен пакет java.awt.im?
>> Поддержка нестандартных методов ввода текста.

51. Для чего предназначен пакет java.awt.im.spi?
>> Интерфейсы для создания нестандартных методов ввода текста.

52. Для чего предназначен пакет java.lang?
>> Базовые классы языка Java.

53. Для чего предназначен пакет java.lang.ref?
>> Управление ссылками на объекты.

54. В папке build проекта NetBeans находятся?
>> хранятся скомпилированные файлы классов, имеющие расширение .class.

55. В папке dist проекта NetBeans находятся?
>> файлы, предназначенные для распространения как результат компиляции (модуль JAR приложения или библиотеки, а также документация к нему).

56. В папке nbproject проекта NetBeans находятся?
>> находится служебная информация по проекту.

57. В папке src проекта NetBeans находятся?
>> исходные коды классов. Кроме того, там же хранится информация об экранных формах (которые будут видны на экране в виде окон с кнопками, текстом и т.п.). Она содержится в XML-файлах, имеющих расширение .form.

58. В папке test проекта NetBeans находятся?
>> сопроводительные тесты, предназначенные для проверки правильности работы классов проекта.

59. Команды документации (символы метаданных) @see?
>> применяется для создания в документе гиперссылок на другие комментарии. Можно использовать для любых конструкций (классов, методов и т.д. ).

60. Команды документации (символы метаданных) @since?
>> Информация о версии JDK, начиная с которой введён или работоспособен класс или интерфейс.

61. Команды документации (символы метаданных) @throws?
>> Информация об исключительных ситуациях, которые могут возбуждаться методом.

62. Команды документации (символы метаданных) @param?
>> информация о параметре метода.

63. Команды документации (символы метаданных) @deprecated?
>> информация о том, что данный метод устарел и в последующих версиях будет ликвидирован. При попытке использования таких методов компилятор выдаёт программисту предупреждение (warning) о том, что метод устарел, хотя и компилирует проект.

64. Целые типы, тип byte?
>> Однобайтовое целое число (8-битное целое со знаком).

65. Целые типы, тип short?
>> Короткое целое число (16- битное целое со знаком).

66. Целые типы, тип char?
>> Символьный тип (беззнаковое 16- битное целое).

67. Целые типы, тип int?
>> Целое число (32- битное целое со знаком).

68. Целые типы, тип long?
>> Длинное целое число (64- битное целое со знаком).

69. Выберите правильный вариант a,b,c,d чтобы результат выражения a&&b || c^ d являлся истиной?
>> все ответы верны
— a=true, b=true, c=false, d=true
— a=false, b=false, c=false, d=true
— a=false, b=false, c=true, d=false
— a=true, b=true, c=true, d=true

70. Выберите правильный вариант a,b,c,d чтобы результат выражения a&&(b || c)^ d являлся ложью?
>> все ответы верны
— a=false, b=true, c=false, d=true
— a=true, b=true, c=false, d=true
— a=false, b=false, c=false, d=true
— a=false, b=false, c=false, d=false

71. Вещественные типы, размер типа float?
>> 4 байта

72. Вещественные типы, размер типа double?
>> 8 байт

73. Float f1 = new Float(Float.NaN);
Float f2 = new Float(Float.NaN);
System.out.println( «»+ (f1 == f2)+» «+f1.equals(f2)+ » «+(Float.NaN == Float.NaN) );
Что будет выведено в результате выполнения данного куска кода?
>> false true false

74. int i = 0;
i++;
System.out.print(i);
i = i++;
System.out.println(i); Что выведет данный код?
>> 11

75. int i = 0, j = 5;
tp: for (;;) < i++;
for (;;) < if (i >—j) breaktp; > >
System.out.println(«i =» + i + «, j = » + j);> Что произойдет во время компиляции и выполнения данного фрагмента кода?
>> Ошибка компиляции.

76. int i = 1; //1
i = -+(10 + 2 + i); //2
++i—; //3
System.out.println(i); В какой строке(-ах) кода содержится ошибка?
>> 3.

77. Integer i = newInteger(«10»);
if (i.toString().intern() == i.toString().intern()) System.out.println(«Равный»);
> else System.out.println(«Не равный»); >> Результат выполнения программы?
>> Выведется “Равный”.

78. public class Main public static void main(String[] args) Boolean b1 = new Boolean(«true»); System.out.print(b1 +» «);
b1 =new Boolean(«tRuE»); System.out.print(b1 +» «);
b1 =new Boolean(«test»); System.out.print(b1 +» «);
b1 =new Boolean(true); System.out.print(b1 +» «);
b1 = true; System.out.println(b1); >> каким будет результат компиляции и выполнения кода?
>> true true false true true

79. public class Test static < System.out.print("Bo-Bo ");>
public static void main(String[] args) System.out.print(«Hello, World! «); >
static < System.out.println("Go-Go "); System.exit(0); >> что выведет код?
>> Bo-Bo Go-Go

80. int i = 1; //1
i = -+(10 + 2 + 1); //2
++i—; //3
System.out.println(i); В какой строке(-ах) кода содержится ошибка?
>> 3

81. Integer a = 128; Integer b = 128;
Integer c = -128; Integer d = -128;
System.out.print((a == b)+» «);
System.out.println(c == d); Что будет выведено на экран?
>> false true

82. Boolean b = new Boolean(«Hello»);
System.out.println(b); Какой результат выполнения данного кода?
>> false

83. public class Test static < i =5; >
static int i = 6;
public static void main(String[] args) System.out.println(i); >> Выберите правильный ответ?
>> 6

84. public class MathTest public static void main(String[] args) System.out.print(((-7 % 5)>(7 % -5))+» «);
System.out.println(Math.abs(Math.ceil(-2.5))>
Что будет напечатано в результате выполнения данного кода?
>> false true

85. int i = 0;
System.out.print(i++);
System.out.println(i); Результат кода?
>> 01

86. int j = 0;
System.out.print(++j);
System.out.println(j); Результат кода?
>> 11

87. public class TestClass
int i = getInt();
int k = 20;
public int getInt()
public static void main(String[] args)
TestClass t = new TestClass ();
System.out.println(t.i+» «+t.k); >>
Что выведет этот код?
>> Будет выведено на печать 1 20

88. int x = 0;
int y = 10;
do< y--;
++x;> while(x<5);
System.out.print(x+»,»+y); >
Что напечатает этот код?
>> напечатает 5 5

89. Дана строка:
String s=»true,false»;
Каким способом можно сформировать новую строку, равную “test”?
>> String n = s.substring(0,1) + s.substring(9,10) + s.substring(8,9) + s.substring(0,1)

90. int result = 12+2*5%3-15/4;
String x=12-6+»Hello»+7+5;
System.out.println(result+»-«+x);
Что будет выведено на консоль?
>> 10-6Hello75

91. String s1=»Строка типа String»;
String s2=»Строка«;
s2+=» типа String»;
if(s1==s2) System.out.println(«s1 равно s2″);
else System.out.println(«s1 не равно s2″);
Что выведет этот код?
>> s1 не равно s2

92. String s1=»Строка типа String»;
String s2=»Строка«;
s2+=» типа String»;
if(s1.equals(s2)) System.out.println(«s1 равно s2″);
else System.out.println(«s1 не равно s2″);
Что выведет этот код?
>> s1 равно s2

93. String s1=»Строка»;
String s2=»Строка»;
if(s1==s2) System.out.println(«s1 равно s2″);
else System.out.println(«s1 не равно s2″);
Что выведет этот код?
>> s1 равно s2

94. String s=»»;
s+= 1+2+3;
System.out.println(s);
Что выведет этот код?
>> 6

95. String s=»Сумма =»+1+2+3;
System.out.println(s);
Что выведет этот код?
>> Сумма=123

96. String s=1+2+» не равно «+1+2;
System.out.println(s);
Что выведет этот код?
>> 3 не равно 12

97. Работа с графикой. Функция clearRect(x,y,w,h)?
>> Очистка прямоугольника (заполнение текущим цветом).

98. Работа с графикой.Функция fill3DRect(x,y,w,h, isRaised)?
>> Вывод «объемного» прямоугольника, заполненного текущим цветом.

99. Работа с графикой.Функция fillPolygon(Polygon p)?
>> Вывод многоугольника, заполненного текущим цветом.

100. Работа с графикой. Функция copyArea(x,y,w,h,dx,dy)?
>> Копирование области на новое место.

101. Переменные класса File. String pathSeparator?
>> Содержит строку с символом разделителя пути в операционной системе. Это «/» в Unix-подобных системах и «\» в Windows.

102. Переменные класса File.char pathSeparatorChar?
>> Содержит символ разделителя пути в операционной системе. Это «/» в Unix-подобных системах и «\» в Windows.

103. Переменные класса File.String separator?
>> Содержит строку с символом разделителя между именами файлов и файловых масок в операционной системе.

104. Переменные класса File. char separatorChar?
>> Содержит символ разделителя между именами файлов и файловых масок в операционной системе.

105. Методы класса File.canRead() ?
>> Возвращает true в случае, когда файл (или папка) с заданным в конструкторе именем существует и доступен по чтению. Иначе false.

106. Методы класса File.setReadOnly() ?
>> Возвращает true в случае, когда файл (или папка) с заданным в конструкторе именем существует, и ему удалось установить статус «доступен только по чтению». Иначе false.

107. Методы класса File. isDirectory() ?
>> Возвращает true в случае, когда файл или папка с заданным в конструкторе именем существует и является папкой. Иначе false.

108. Методы класса File. isFile() ?
>> Возвращает true в случае, когда файл или папка с заданным в конструкторе именем существует и является файлом. Иначе false.

109. Методы класса File.isHidden() ?
>> Возвращает true в случае, когда файл или папка с заданным в конструкторе именем существует и является скрытым. Иначе false.

110. Методы класса File. lastModified() ?
>> Возвращает время последней модификации файла, если он существует и доступен по чтению. Иначе 0L.

111. Методы класса File. setLastModified(long time) ?
>> Устанавливает время последней модификации файла. Возвращает true, если он существует и доступен по записи. Иначе false.

112. Методы класса File.getName() ?
>> Возвращает короткое имя файла или папки.

113. Методы класса File.getAbsolutePath() ?
>> Возвращает абсолютный путь к файлу или папке, включая имя файла. При этом, если в имени файла в конструкторе была задана относительная адресация, соответствующая часть пути сохраняется в возвращаемой строке.

114. Методы класса File. getCanonicalPath() ?
>> Возвращает абсолютный путь к файлу или папке, включая имя файла. При этом, если в имени файла в конструкторе была задана относительная адресация, соответствующая часть пути заменяется в возвращаемой строке на канонический вариант адресации – без элементов относительной адресации.

115. Методы класса File.compareTo(File f) ?
>> Сравнение имён файлов (папок), сопоставляемых текущему файловому объекту и объекту f. Возвращает 0 в случае, когда абсолютные имена файлов (папок) совпадают. Иначе возвращает число, зависящее от разницы в длинах имён и кодов, составляющих их символов.

116. Методы класса File.isAbsolute() ?
>> Возвращает true в случае, когда адресация к имени файла (папки) текущего файлового объекта является абсолютной. Хотя может содержать элементы относительной адресации, то есть не быть канонической.

117. Методы класса File.equals(Object obj) ?
>> Возвращает true тогда и только тогда, когда текущий объект и параметр obj соответствует одному и тому же файлу (папке).

118. Методы класса File.createTempFile(String prefix, String suffix) ?
>> Обеспечивает создание пустого файла (или папки), задаваемого коротким именем prefix+suffix в папке операционной системы, предназначенной для временных файлов. Возвращает ссылку на объект. Префикс должен быть не менее 3 символов.

119. Методы класса File.mkdir() ?
>> Попытка создания папки по имени, которое было задано в конструкторе объекта. Возвращает true в случае успешного создания и false в других случаях.

120. Методы класса File.renameTo(File dest) ?
>> Попытка переименования файла или папки с имени, которое было задано в конструкторе объекта, на новое, задаваемое параметром dest. Возвращает true в случае успешного переименования и false в других случаях.

121. Методы класса File.getAbsoluteFile() ?
>> Создание нового файлового объекта по абсолютному пути, соответствующему текущему файловому объекту.

122. Методы класса File.list() ?
>> Возвращает массив строк (список) коротких имён, находящихся в папке файлов и папок. Имена элементов, находящихся во вложенных папках, не показываются. Если файловый объект не соответствует существующей папке, возвращает null.

123. Конструкторы?
>> это методы, используемые для инициализации объектов в процессе их реализации.

124. Как объекты обмениваются информацией?
>> Объекты общаются друг с другом посредством посылки сообщений.

125. Что такое this?
>> ссылка, с помощью которой объект обращается к самому себе.

126. Класс ?
>> Класс – это структурный тип данных, который включает описание полей данных, а также процедур и функций, работающих с этими полями данных.

127. Процедуры и функции, работающие с полями данных класса?
>> Называются методами.

128. Объединение полей данных и процедур и функций, работающих с этими данными, в единый пакет, при наличии специальных правил доступа к элементам пакета?
>> Инкапсуляция.

129. Основные средства разработки классов. Наследование?
>> Конструирование новых более сложных классов из уже имеющихся посредством добавления полей и определения новых методов (принцип иерархичности).

130. Основные средства разработки классов. Полиморфизм?
>> обеспечивает возможность задания различных реализаций некоторого единого по названию метода для классов различных уровней иерархии.

131. Полиморфными объектами или полиморфными переменными называются?
>> переменные, которым в процессе выполнения программы может быть присвоено значение, тип которого отличается от типа переменной.

132. К изменению свойств объекта возможен только через принадлежащие ему?
>> методы.

133. В момент времени объект характеризуется:?
>> Свойствами

134. Программа в объектно-ориентированном программировании состоит из:?
>> событийных процедур.

135. Инкапсулированные в классе процедуры и функции называются?
>> Методы

136. Процесс, при котором различный код и данные различных модулей соединяются друг с другом в процессе исполнения, называют компоновкой?
>> Динамической

137. Область исходного кода программы, из которой допустим нормальный доступ к связанному с идентификатором объекту, называется?
>> Видимостью

138. Конструктором по умолчанию называется такой конструктор, который?
>> не принимает никаких аргументов.

139. Класс-наследник называется . от базового класса?
>> Производным.

140. Что следует ожидать на экране?
System.out.print(«A»+»B»+»C»);
System.out.println(‘A’+’B’+’C’);
>> ABC198

141. int j = 0;
for (int i = 0; i< 10; i++)
j = j++;
System.out.println(j);
Что выведется в результате?
>> 0

142. int x, y;
int i;
x = 1;
for (i = 0; i< 10; i++)

Что выведется в результате?
>> 3 5 7 9 11 13 15 17 19 21

143. int x, y;
int i;
x = 1;
for (i = 0; i< 10; i++)

Что выведется в результате?
>> 2 4 6 8 10 12 14 16 18 20

144. int x=0;
for(int count=10; count < 5; count++)
x += count ;>
Чему равна х?
>> 0

145. for(inti=-10; i
0) break;
System.out.print(i + » «) ;>,
Что выведется в результате?
>> -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0

147. Каков будет результат следующего примера?
Point p = new Point(1,2);
int a =p.x;
p = new Point(3,4);
System.out.println(a);
>> 1

148. Каков будет результат следующего примера?
Point p1 = new Point(3,4);
Point p2 = p1;
p1.x = 5;
p1 = new Point(4,4);
System.out.println(p2.x-p1.x);
>> 1

149. Каков будет результат следующих действий?
Point p1 = new Point(2,3);
Point p2 = new Point(2,3);
System.out.print(p1==p2);
p2=p1;
p1.x = 3;
System.out.print(» «);
System.out.println(p1==p2);
>> false true

150. Каков будет результат следующего примера?
public class testClass
public static void process (int x)

public static void main(String[] args)
int x=3; process(x);
System.out.println(x); >>
>> 3

151. Что будет напечатано в консоли в результате выполнения следующего кода:
System.out.println((byte)383+» «+(byte)384+» «+(byte)-384); ?
>> 127 -128 -128

152. Каков будет результат следующего примера?
char c = 65;
System.out.print(c);
System.out.print(+c);
System.out.print(«=»+c);
>> A65=A

153. Каков будет результат следующего примера?
class Parent
class Child extends Parent
public class testClass
public static void main(String[] args)
Child c = new Child(); System.out.print(c.a);
Parent p=c; System.out.print(p.a); >>
>> 32

154. Каков будет результат следующего примера?
class Parent
public void printX()>
class Child extends Parent
public class testClass
public static void main(String[] args)
new Child().printX(); >>
>> 0

155. Каков будет результат следующего примера?
class Parent
class Child extends Parent
public class testClass
public static void main(String[] args)
Child.a=10; Parent.a=5; System.out.println(Child.a); >>
>> 5

156. Каков будет результат следующего примера?
int i,j;
lab:for(i=0;i<6;i++)
for(j=3;j>1;j—)
if(i==j) > >
>> 2

157. Каков будет результат следующей программы?
public class testClass public static void main(String[] args) inti =5;
while(i=5) <
System.out.println(i++); >>>
>> Ошибка компиляции.

158. Каков будет результат следующего примера?
int b=5;
System.out.print(b+(b=3));
System.out.print((b=3)+3);b=5;
System.out.print(b+=(b=3));
>> 868

159. Дан код:
class Quest3
public static void main(String s[ ])
String args;
System.out.print(args + s);
>>
Результатом компиляции кода будет?
>> ошибка компиляции: переменная args используется до инициализации.

160. Дан код:
public class Quest5
public static void main()
System.out.print(«А«); >
public static void main(String args)
System.out.print(«Б«); >
public static void main(String[] args)
System.out.print(«В»);>>
Что будет выведено в результате компиляции и запуска?
>> B

161. Какие из следующихутверждений истинные?
a-nonstatic-метод не может быть вызван из статического метода;
b-static-метод не может быть вызван из нестатического метода;
c-private-метод не может быть вызван из другого метода этого класса;
d-final-метод не может быть статическим.
>> a

162. Дан код:
public class Quest5

static
Quest5()
public static void main(String[] args)
System.out.print(«4»); >>
В результате при компиляции и запуске будет выведено?
>> 24

163. Какие из объявлений корректны, если
classOwner
classInner
>>?
>> new Owner().new Inner();

164. Дан код:
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));>>
В результате при компиляции запуске будет выведено?
>>

165. Экземпляром какого класса является поле System.in?
>> java.io.InputStream;

166. Какой абстрактный класс является суперклассом для всех классов, используемых для чтения байтов?
>> InputStream

167. Какой интерфейс наиболее пригоден для создания класса, содержащего несортированные уникальные объекты?
>> Set

168. Дан код:



Какой код читает параметр count в переменную i?

>> int i = new Integer(getParameter(»count»)).intValue()

Исключения в Java, Часть I (try-catch-finally)

Это первая часть статьи, посвященной такому языковому механизму Java как исключения (вторая (checked/unchecked) вот). Она имеет вводный характер и рассчитана на начинающих разработчиков или тех, кто только приступает к изучению языка.

Также я веду курс «Scala for Java Developers» на платформе для онлайн-образования udemy.com (аналог Coursera/EdX).

1. Ключевые слова: try, catch, finally, throw, throws
  • try
  • catch
  • finally
  • throw
  • throws

«Магия» (т.е. некоторое поведение никак не отраженное в исходном коде и потому неповторяемое пользователем) исключений #1 заключается в том, что catch, throw, throws можно использовать исключительно с java.lang.Throwable или его потомками.

throws:
Годится

public class App < public static void main(String[] args) throws Throwable <>> 
public class App < public static void main(String[] args) throws String <>> >> COMPILATION ERROR: Incompatible types: required 'java.lang.Throwable', found: 'java.lang.String' 

catch:
Годится

public class App < public static void main(String[] args) < try < >catch (Throwable t) <> > > 
public class App < public static void main(String[] args) < try < >catch (String s) <> > > >> COMPILATION ERROR: Incompatible types: required 'java.lang.Throwable', found: 'java.lang.String' 

throw:
Годится

public class App < public static void main(String[] args) < // Error - потомок Throwable throw new Error(); >> 
public class App < public static void main(String[] args) < throw new String("Hello!"); >> >> COMPILATION ERROR: Incompatible types: required 'java.lang.Throwable', found: 'java.lang.String' 

Кроме того, throw требуется не-null аргумент, иначе NullPointerException в момент выполнения

public class App < public static void main(String[] args) < throw null; >> >> RUNTIME ERROR: Exception in thread "main" java.lang.NullPointerException 

throw и new — это две независимых операции. В следующем коде мы независимо создаем объект исключения и «бросаем» его

public class App < public static void main(String[] args) < Error ref = new Error(); // создаем экземпляр throw ref; // "бросаем" его >> >> RUNTIME ERROR: Exception in thread "main" java.lang.Error 

Однако, попробуйте проанализировать вот это

public class App < public static void main(String[] args) < f(null); >public static void f(NullPointerException e) < try < throw e; >catch (NullPointerException npe) < f(npe); >> > >> RUNTIME ERROR: Exception in thread "main" java.lang.StackOverflowError 
2. Почему используем System.err, а не System.out

System.out — buffered-поток вывода, а System.err — нет. Таким образом вывод может быть как таким

public class App < public static void main(String[] args) < System.out.println("sout"); throw new Error(); >> >> RUNTIME ERROR: Exception in thread "main" java.lang.Error >> sout 

Так и вот таким (err обогнало out при выводе в консоль)

public class App < public static void main(String[] args) < System.out.println("sout"); throw new Error(); >> >> sout >> RUNTIME ERROR: Exception in thread "main" java.lang.Error 

Давайте это нарисуем

 буфер сообщений +----------------+ +->| msg2 msg1 msg0 | --> out / +----------------+ \ / +-> +--------+ ВАШЕ ПРИЛОЖЕНИЕ | КОНСОЛЬ| \ +-> +--------+ \ / +------------------------> err нет буфера, сразу печатаем 

когда Вы пишете в System.err — ваше сообщение тут же выводится на консоль, но когда пишете в System.out, то оно может на какое-то время быть буферизированно. Stacktrace необработанного исключение выводится через System.err, что позволяет им обгонять «обычные» сообщения.

3. Компилятор требует вернуть результат (или требует молчать)

Если в объявлении метода сказано, что он возвращает НЕ void, то компилятор зорко следит, что бы мы вернули экземпляр требуемого типа или экземпляр типа, который можно неявно привести к требуемому

public class App < public double sqr(double arg) < // надо double return arg * arg; // double * double - это double >> 
public class App < public double sqr(double arg) < // надо double int k = 1; // есть int return k; // можно неявно преобразовать int в double >> 
// на самом деле, компилятор сгенерирует байт-код для следующих исходников public class App < public double sqr(double arg) < // надо double int k = 1; // есть int return (double) k; // явное преобразование int в double >> 

вот так не пройдет (другой тип)

public class App < public static double sqr(double arg) < return "hello!"; >> >> COMPILATION ERROR: Incompatible types. Required: double. Found: java.lang.String 

Вот так не выйдет — нет возврата

public class App < public static double sqr(double arg) < >> >> COMPILATION ERROR: Missing return statement 

и вот так не пройдет (компилятор не может удостовериться, что возврат будет)

public class App < public static double sqr(double arg) < if (System.currentTimeMillis() % 2 == 0) < return arg * arg; // если currentTimeMillis() - четное число, то все ОК >// а если нечетное, что нам возвращать? > > >> COMPILATION ERROR: Missing return statement 

Компилятор отслеживает, что бы мы что-то вернули, так как иначе непонятно, что должна была бы напечатать данная программа

public class App < public static void main(String[] args) < double d = sqr(10.0); // ну, и чему равно d? System.out.println(d); >public static double sqr(double arg) < // nothing >> >> COMPILATION ERROR: Missing return statement 

Из-забавного, можно ничего не возвращать, а «повесить метод»

public class App < public static double sqr(double arg) < while (true); // Удивительно, но КОМПИЛИРУЕТСЯ! >> 

Тут в d никогда ничего не будет присвоено, так как метод sqr повисает

public class App < public static void main(String[] args) < double d = sqr(10.0); // sqr - навсегда "повиснет", и System.out.println(d); // d - НИКОГДА НИЧЕГО НЕ БУДЕТ ПРИСВОЕНО! >public static double sqr(double arg) < while (true); // Вот тут мы на века "повисли" >> 

Компилятор пропустит «вилку» (таки берем в квадрат ИЛИ висим)

public class App < public static double sqr(double arg) < if (System.currentTimeMillis() % 2 == 0) < return arg * arg; // ну ладно, вот твой double >else < while (true); // а тут "виснем" навсегда >> > 

Но механизм исключений позволяет НИЧЕГО НЕ ВОЗВРАЩАТЬ!

public class App < public static double sqr(double arg) < throw new RuntimeException(); >> 

Итак, у нас есть ТРИ варианта для компилятора

public class App < public static double sqr(double arg) else if (time % 2 == 1) < < while (true); // не, я решил "повиснуть" >else < throw new RuntimeException(); // или бросить исключение >> > 

Но КАКОЙ ЖЕ double вернет функция, бросающая RuntimeException?
А НИКАКОЙ!

public class App < public static void main(String[] args) < // sqr - "сломается" (из него "выскочит" исключение), double d = sqr(10.0); // выполнение метода main() прервется в этой строчке и // d - НИКОГДА НИЧЕГО НЕ БУДЕТ ПРИСВОЕНО! System.out.println(d); // и печатать нам ничего не придется! >public static double sqr(double arg) < throw new RuntimeException(); // "бросаем" исключение >> >> RUNTIME ERROR: Exception in thread "main" java.lang.RuntimeException 

Подытожим: бросаемое исключение — это дополнительный возвращаемый тип. Если ваш метод объявил, что возвращает double, но у вас нет double — можете бросить исключение. Если ваш метод объявил, что ничего не возвращает (void), но у вам таки есть что сказать — можете бросить исключение.

Давайте рассмотрим некоторый пример из практики.

Задача: реализовать функцию, вычисляющую площадь прямоугольника

public static int area(int width, int height)

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

public static int area(int width, int height) < return width * height; // тут просто перемножаем >

Вопрос: что делать, если мы обнаружили, что хотя бы один из аргументов — отрицательное число?
Если просто умножить, то мы пропустили ошибочные данные дальше. Что еще хуже, возможно, мы «исправили ситуацию» — сказали что площадь прямоугольника с двумя отрицательными сторонами -10 и -20 = 200.

Мы не можем ничего не вернуть

public static int area(int width, int height) < if (width < 0 || height < 0) < // у вас плохие аргументы, извините >else < return width * height; >> >> COMPILATION ERROR: Missing return statement 

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

public static int area(int width, int height) < if (width < 0 || height < 0) < System.out.println("Bad . "); >return width * height; > 

Можно вернуть специальное значение, показывающее, что что-то не так (error code), но кто гарантирует, что его прочитают, а не просто воспользуются им?

public static int area(int width, int height) < if (width < 0 || height < 0) < return -1; // специальное "неправильное" значение площади >return width * height; > 

Можем, конечно, целиком остановить виртуальную машину

public static int area(int width, int height) < if (width < 0 || height < 0) < System.exit(0); >return width * height; > 

Но «правильный путь» таков: если обнаружили возможное некорректное поведение, то
1. Вычисления остановить, сгенерировать сообщение-поломку, которое трудно игнорировать, предоставить пользователю информацию о причине, предоставить пользователю возможность все починить (загрузить белье назад и повторно нажать кнопку старт)

public static int area(int width, int height) 
4. Нелокальная передача управления (nonlocal control transfer)

Механизм исключительных ситуация (исключений) — это механизм НЕЛОКАЛЬНОЙ ПЕРЕДАЧИ УПРАВЛЕНИЯ.
Что под этим имеется в виду?
Программа, в ходе своего выполнения (точнее исполнения инструкций в рамках отдельного потока), оперирует стеком («стопкой») фреймов. Передача управления осуществляется либо в рамках одного фрейма
public class App < public static void main(String[] args) < // Пример: ОПЕРАТОР ПОСЛЕДОВАТЕЛЬНОСТИ int x = 42; // первый шаг int y = x * x; // второй шаг x = x * y; // третий шаг . >> 
public class App < public static void main(String[] args) < // Пример: ОПЕРАТОР ВЕТВЛЕНИЯ if (args.length >2) < первый шаг // второй шаг или тут . >else < // или тут . >// третий шаг . > > 
public class App < public static void main(String[] args) < // Пример: ОПЕРАТОР ЦИКЛА do..while int x = 1; do < . >while (x++ < 10); . >> 

и другие операторы.

  • вызов метода: создаем новый фрейм, помещаем его на верхушку стека и переходим в него
  • выход из метода: возвращаемся к предыдущему фрейму (через return или просто кончились инструкции в методе)

return — выходим из ОДНОГО фрейма (из фрейма #4(метод h()))

public class App < public static void main(String[] args) < System.err.println("#1.in"); f(); // создаем фрейм, помещаем в стек, передаем в него управление System.err.println("#1.out"); // вернулись >// выходим из текущего фрейма, кончились инструкции public static void f() < System.err.println(". #2.in"); g(); // создаем фрейм, помещаем в стек, передаем в него управление System.err.println(". #2.out"); //вернулись >// выходим из текущего фрейма, кончились инструкции public static void g() < System.err.println(". . #3.in"); h(); // создаем фрейм, помещаем в стек, передаем в него управление System.err.println(". . #3.out"); // вернулись >// выходим из текущего фрейма, кончились инструкции public static void h() < System.err.println(". . . #4.in"); if (true) < System.err.println(". . . #4.RETURN"); return; // выходим из текущего фрейма по 'return' >System.err.println(". . . #4.out"); // ПРОПУСКАЕМ > > >> #1.in >> . #2.in >> . . #3.in >> . . . #4.in >> . . . #4.RETURN >> . . #3.out >> . #2.out >> #1.out 

throw — выходим из ВСЕХ фреймов

public class App < public static void main(String[] args) < System.err.println("#1.in"); f(); // создаем фрейм, помещаем в стек, передаем в него управление System.err.println("#1.out"); // ПРОПУСТИЛИ! >public static void f() < System.err.println(". #2.in"); g(); // создаем фрейм, помещаем в стек, передаем в него управление System.err.println(". #2.out"); // ПРОПУСТИЛИ! >public static void g() < System.err.println(". . #3.in"); h(); // создаем фрейм, помещаем в стек, передаем в него управление System.err.println(". . #3.out"); // ПРОПУСТИЛИ! >public static void h() < System.err.println(". . . #4.in"); if (true) < System.err.println(". . . #4.THROW"); throw new Error(); // выходим со всей пачки фреймов ("раскрутка стека") по 'throw' >System.err.println(". . . #4.out"); // ПРОПУСТИЛИ! > > >> #1.in >> . #2.in >> . . #3.in >> . . . #4.in >> . . . #4.THROW >> RUNTIME ERROR: Exception in thread "main" java.lang.Error 

При помощи catch мы можем остановить летящее исключение (причина, по которой мы автоматически покидаем фреймы).
Останавливаем через 3 фрейма, пролетаем фрейм #4(метод h()) + пролетаем фрейм #3(метод g()) + фрейм #2(метод f())

public class App < public static void main(String[] args) < System.err.println("#1.in"); try < f(); // создаем фрейм, помещаем в стек, передаем в него управление >catch (Error e) < // "перехватили" "летящее" исключение System.err.println("#1.CATCH"); // и работаем >System.err.println("#1.out"); // работаем дальше > public static void f() < System.err.println(". #2.in"); g(); // создаем фрейм, помещаем в стек, передаем в него управление System.err.println(". #2.out"); // ПРОПУСТИЛИ! >public static void g() < System.err.println(". . #3.in"); h(); // создаем фрейм, помещаем в стек, передаем в него управление System.err.println(". . #3.out"); // ПРОПУСТИЛИ! >public static void h() < System.err.println(". . . #4.in"); if (true) < System.err.println(". . . #4.THROW"); throw new Error(); // выходим со всей пачки фреймов ("раскрутка стека") по 'throw' >System.err.println(". . . #4.out"); // ПРОПУСТИЛИ! > > >> #1.in >> . #2.in >> . . #3.in >> . . . #4.in >> . . . #4.THROW >> #1.CATCH >> #1.out 

Обратите внимание, стандартный сценарий работы был восстановлен в методе main() (фрейм #1)

Останавливаем через 2 фрейма, пролетаем фрейм #4(метод h()) + пролетаем фрейм #3(метод g())

public class App < public static void main(String[] args) < System.err.println("#1.in"); f(); // создаем фрейм, помещаем в стек, передаем в него управление System.err.println("#1.out"); // вернулись и работаем >public static void f() < System.err.println(". #2.in"); try < g(); // создаем фрейм, помещаем в стек, передаем в него управление >catch (Error e) < // "перехватили" "летящее" исключение System.err.println(". #2.CATCH"); // и работаем >System.err.println(". #2.out"); // работаем дальше > public static void g() < System.err.println(". . #3.in"); h(); // создаем фрейм, помещаем в стек, передаем в него управление System.err.println(". . #3.out"); // ПРОПУСТИЛИ! >public static void h() < System.err.println(". . . #4.in"); if (true) < System.err.println(". . . #4.THROW"); throw new Error(); // выходим со всей пачки фреймов ("раскрутка стека") по 'throw' >System.err.println(". . . #4.out"); // ПРОПУСТИЛИ! > > >> #1.in >> . #2.in >> . . #3.in >> . . . #4.in >> . . . #4.THROW >> . #2.CATCH >> . #2.out >> #1.out 

Останавливаем через 1 фрейм (фактически аналог return, просто покинули фрейм «другим образом»)

public class App < public static void main(String[] args) < System.err.println("#1.in"); f(); // создаем фрейм, помещаем в стек, передаем в него управление System.err.println("#1.out"); // вернулись и работаем >public static void f() < System.err.println(". #2.in"); g(); // создаем фрейм, помещаем в стек, передаем в него управление System.err.println(". #2.out"); // вернулись и работаем >public static void g() < System.err.println(". . #3.in"); try < h(); // создаем фрейм, помещаем в стек, передаем в него управление >catch (Error e) < // "перехватили" "летящее" исключение System.err.println(". . #3.CATCH"); // и работаем >System.err.println(". . #3.out"); // работаем дальше > public static void h() < System.err.println(". . . #4.in"); if (true) < System.err.println(". . . #4.THROW"); throw new Error(); // выходим со всей пачки фреймов ("раскрутка стека") по 'throw' >System.err.println(". . . #4.out"); // ПРОПУСТИЛИ! > > >> #1.in >> . #2.in >> . . #3.in >> . . . #4.in >> . . . #4.THROW >> . . #3.CATCH >> . . #3.out >> . #2.out >> #1.out 

Итак, давайте сведем все на одну картинку

// ---Используем RETURN--- // ---Используем THROW--- // Выход из 1-го фрейма // Выход из ВСЕХ (из 4) фреймов #1.in #1.in . #2.in . #2.in . . #3.in . . #3.in . . . #4.in . . . #4.in . . . #4.RETURN . . . #4.THROW . . #3.out RUNTIME EXCEPTION: Exception in thread "main" java.lang.Error . #2.out #1.out // ---Используем THROW+CATCH--- // Выход из 3-х фреймов // Выход из 2-х фреймов // Выход из 1-го фрейма #1.in #1.in #1.in . #2.in . #2.in . #2.in . . #3.in . . #3.in . . #3.in . . . #4.in . . . #4.in . . . #4.in . . . #4.THROW . . . #4.THROW . . . #4.THROW #1.CATCH . #2.CATCH . . #3.CATCH #1.out . #2.out . . #3.out #1.out . #2.out #1.out 
5. try + catch (catch — полиморфен)

Напомним иерархию исключений

 Object | Throwable / \ Error Exception | RuntimeException 

То, что исключения являются объектами важно для нас в двух моментах
1. Они образуют иерархию с корнем java.lang.Throwable (java.lang.Object — предок java.lang.Throwable, но Object — уже не исключение)
2. Они могут иметь поля и методы (в этой статье это не будем использовать)

По первому пункту: catch — полиморфная конструкция, т.е. catch по типу Parent перехватывает летящие экземпляры любого типа, который является Parent-ом (т.е. экземпляры непосредственно Parent-а или любого потомка Parent-а)

public class App < public static void main(String[] args) < try < System.err.print(" 0"); if (true) System.err.print(" 1"); > catch (Exception e) < // catch по Exception ПЕРЕХВАТЫВАЕТ RuntimeException System.err.print(" 2"); >System.err.println(" 3"); > > >> 0 2 3 

Даже так: в блоке catch мы будем иметь ссылку типа Exception на объект типа RuntimeException

public class App < public static void main(String[] args) < try < throw new RuntimeException(); >catch (Exception e) < if (e instanceof RuntimeException) < RuntimeException re = (RuntimeException) e; System.err.print("Это RuntimeException на самом деле. "); >else < System.err.print("В каком смысле не RuntimeException. "); >> > > >> Это RuntimeException на самом деле. 

catch по потомку не может поймать предка

public class App < public static void main(String[] args) throws Exception < // пока игнорируйте 'throws' try < System.err.print(" 0"); if (true) System.err.print(" 1"); > catch (RuntimeException e) < System.err.print(" 2"); >System.err.print(" 3"); > > >> 0 >> RUNTIME EXCEPTION: Exception in thread "main" java.lang.Exception 

catch по одному «брату» не может поймать другого «брата» (Error и Exception не находятся в отношении предок-потомок, они из параллельных веток наследования от Throwable)

public class App < public static void main(String[] args) < try < System.err.print(" 0"); if (true) System.err.print(" 1"); > catch (Exception e) < System.err.print(" 2"); >System.err.print(" 3"); > > >> 0 >> RUNTIME EXCEPTION: Exception in thread "main" java.lang.Error 

По предыдущим примерам — надеюсь вы обратили внимание, что если исключение перехвачено, то JVM выполняет операторы идущие ПОСЛЕ последних скобок try+catch.
Но если не перехвачено, то мы
1. не заходим в блок catch
2. покидаем фрейм метода с летящим исключением

А что будет, если мы зашли в catch, и потом бросили исключение ИЗ catch?

public class App < public static void main(String[] args) < try < System.err.print(" 0"); if (true) System.err.print(" 1"); > catch (RuntimeException e) < // перехватили RuntimeException System.err.print(" 2"); if (true) // но бросили Error > System.err.println(" 3"); // пропускаем - уже летит Error > > >> 0 2 >> RUNTIME EXCEPTION: Exception in thread "main" java.lang.Error 

В таком случае выполнение метода тоже прерывается (не печатаем «3»). Новое исключение не имеет никакого отношения к try-catch

Мы можем даже кинуть тот объект, что у нас есть «на руках»

public class App < public static void main(String[] args) < try < System.err.print(" 0"); if (true) System.err.print(" 1"); > catch (RuntimeException e) < // перехватили RuntimeException System.err.print(" 2"); if (true) // и бросили ВТОРОЙ раз ЕГО ЖЕ > System.err.println(" 3"); // пропускаем - опять летит RuntimeException > > >> 0 2 >> RUNTIME EXCEPTION: Exception in thread "main" java.lang.RuntimeException 

И мы не попадем в другие секции catch, если они есть

public class App < public static void main(String[] args) < try < System.err.print(" 0"); if (true) System.err.print(" 1"); > catch (RuntimeException e) < // перехватили RuntimeException System.err.print(" 2"); if (true) // и бросили новый Error > catch (Error e) < // хотя есть cath по Error "ниже", но мы в него не попадаем System.err.print(" 3"); >System.err.println(" 4"); > > >> 0 2 >> RUNTIME EXCEPTION: Exception in thread "main" java.lang.Error 

Обратите внимание, мы не напечатали «3», хотя у нас летит Error а «ниже» расположен catch по Error. Но важный момент в том, что catch имеет отношение исключительно к try-секции, но не к другим catch-секциям.

Как покажем ниже — можно строить вложенные конструкции, но вот пример, «исправляющий» эту ситуацию

public class App < public static void main(String[] args) < try < System.err.print(" 0"); if (true) System.err.print(" 1"); > catch (RuntimeException e) < // перехватили RuntimeException System.err.print(" 2.1"); try < System.err.print(" 2.2"); if (true) // и бросили новый Error System.err.print(" 2.3"); > catch (Throwable t) < // перехватили Error System.err.print(" 2.4"); >System.err.print(" 2.5"); > catch (Error e) < // хотя есть cath по Error "ниже", но мы в него не попадаем System.err.print(" 3"); >System.err.println(" 4"); > > >> 0 2.1 2.2 2.4 2.5 4 
6. try + catch + catch + .

Как вы видели, мы можем расположить несколько catch после одного try.

Но есть такое правило — нельзя ставить потомка после предка! (RuntimeException после Exception)

public class App < public static void main(String[] args) < try < >catch (Exception e) < >catch (RuntimeException e) < >> > >> COMPILATION ERROR: Exception 'java.lang.RuntimeException' has alredy been caught 

Ставить брата после брата — можно (RuntimeException после Error)

public class App < public static void main(String[] args) < try < >catch (Error e) < >catch (RuntimeException e) < >> > 

Как происходит выбор «правильного» catch? Да очень просто — JVM идет сверху-вниз до тех пор, пока не найдет такой catch что в нем указано ваше исключение или его предок — туда и заходит. Ниже — не идет.

public class App < public static void main(String[] args) < try < throw new Exception(); >catch (RuntimeException e) < System.err.println("catch RuntimeException"); >catch (Exception e) < System.err.println("catch Exception"); >catch (Throwable e) < System.err.println("catch Throwable"); >System.err.println("next statement"); > > >> catch Exception >> next statement 

Выбор catch осуществляется в runtime (а не в compile-time), значит учитывается не тип ССЫЛКИ (Throwable), а тип ССЫЛАЕМОГО (Exception)

public class App < public static void main(String[] args) < try < Throwable t = new Exception(); // ссылка типа Throwable указывает на объект типа Exception throw t; >catch (RuntimeException e) < System.err.println("catch RuntimeException"); >catch (Exception e) < System.err.println("catch Exception"); >catch (Throwable e) < System.err.println("catch Throwable"); >System.err.println("next statement"); > > >> catch Exception >> next statement 
7. try + finally

finally-секция получает управление, если try-блок завершился успешно

public class App < public static void main(String[] args) < try < System.err.println("try"); >finally < System.err.println("finally"); >> > >> try >> finally 

finally-секция получает управление, даже если try-блок завершился исключением

public class App < public static void main(String[] args) < try < throw new RuntimeException(); >finally < System.err.println("finally"); >> > >> finally >> Exception in thread "main" java.lang.RuntimeException 

finally-секция получает управление, даже если try-блок завершился директивой выхода из метода

public class App < public static void main(String[] args) < try < return; >finally < System.err.println("finally"); >> > >> finally 

finally-секция НЕ вызывается только если мы «прибили» JVM

public class App < public static void main(String[] args) < try < System.exit(42); >finally < System.err.println("finally"); >> > >> Process finished with exit code 42 

System.exit(42) и Runtime.getRuntime().exit(42) — это синонимы

public class App < public static void main(String[] args) < try < Runtime.getRuntime().exit(42); >finally < System.err.println("finally"); >> > >> Process finished with exit code 42 

И при Runtime.getRuntime().halt(42) — тоже не успевает зайти в finally

public class App < public static void main(String[] args) < try < Runtime.getRuntime().halt(42); >finally < System.err.println("finally"); >> > >> Process finished with exit code 42 

exit() vs halt()
javadoc: java.lang.Runtime#halt(int status)
… Unlike the exit method, this method does not cause shutdown hooks to be started and does not run uninvoked finalizers if finalization-on-exit has been enabled. If the shutdown sequence has already been initiated then this method does not wait for any running shutdown hooks or finalizers to finish their work.

Однако finally-секция не может «починить» try-блок завершившийся исключение (заметьте, «more» — не выводится в консоль)

public class App < public static void main(String[] args) < try < System.err.println("try"); if (true) > finally < System.err.println("finally"); >System.err.println("more"); > > >> try >> finally >> Exception in thread "main" java.lang.RuntimeException 

Трюк с «if (true) <. >» требуется, так как иначе компилятор обнаруживает недостижимый код (последняя строка) и отказывается его компилировать

public class App < public static void main(String[] args) < try < System.err.println("try"); throw new RuntimeException(); >finally < System.err.println("finally"); >System.err.println("more"); > > >> COMPILER ERROR: Unrechable statement 

И finally-секция не может «предотвратить» выход из метода, если try-блок вызвал return («more» — не выводится в консоль)

public class App < public static void main(String[] args) < try < System.err.println("try"); if (true) > finally < System.err.println("finally"); >System.err.println("more"); > > >> try >> finally 

Однако finally-секция может «перебить» throw/return при помощи другого throw/return

public class App < public static void main(String[] args) < System.err.println(f()); >public static int f() < try < return 0; >finally < return 1; >> > >> 1 
public class App < public static void main(String[] args) < System.err.println(f()); >public static int f() < try < throw new RuntimeException(); >finally < return 1; >> > >> 1 
public class App < public static void main(String[] args) < System.err.println(f()); >public static int f() < try < return 0; >finally < throw new RuntimeException(); >> > >> Exception in thread "main" java.lang.RuntimeException 
public class App < public static void main(String[] args) < System.err.println(f()); >public static int f() < try < throw new Error(); >finally < throw new RuntimeException(); >> > >> Exception in thread "main" java.lang.RuntimeException 

finally-секция может быть использована для завершающего действия, которое гарантированно будет вызвано (даже если было брошено исключение или автор использовал return) по окончании работы

// open some resource try < // use resource >finally < // close resource >

Например для освобождения захваченной блокировки

Lock lock = new ReentrantLock(); . lock.lock(); try < // some code >finally

Или для закрытия открытого файлового потока

InputStream input = new FileInputStream(". "); try < // some code >finally

Специально для этих целей в Java 7 появилась конструкция try-with-resources, ее мы изучим позже.

Вообще говоря, в finally-секция нельзя стандартно узнать было ли исключение.
Конечно, можно постараться написать свой «велосипед»

public class App < public static void main(String[] args) < System.err.println(f()); >public static int f() < long rnd = System.currenttimeMillis(); boolean finished = false; try < if (rnd % 3 == 0) < throw new Error(); >else if (rnd % 3 == 1) < throw new RuntimeException(); >else < // nothing >finished = true; > finally < if (finished) < // не было исключений >else < // было исключение, но какое? >> > > 

Не рекомендуемые практики
— return из finally-секции (можем затереть исключение из try-блока)
— действия в finally-секции, которые могут бросить исключение (можем затереть исключение из try-блока)

8. try + catch + finally
public class App < public static void main(String[] args) < try < System.err.print(" 0"); // nothing System.err.print(" 1"); >catch(Error e) < System.err.print(" 2"); >finally < System.err.print(" 3"); >System.err.print(" 4"); > > >> 0 1 3 4 

Не заходим в catch, заходим в finally, продолжаем после оператора

Есть исключение и есть подходящий catch

public class App < public static void main(String[] args) < try < System.err.print(" 0"); if (true) System.err.print(" 1"); > catch(Error e) < System.err.print(" 2"); >finally < System.err.print(" 3"); >System.err.print(" 4"); > > >> 0 2 3 4 

Заходим в catch, заходим в finally, продолжаем после оператора

Есть исключение но нет подходящего catch

public class App < public static void main(String[] args) < try < System.err.print(" 0"); if (true) System.err.print(" 1"); > catch(Error e) < System.err.print(" 2"); >finally < System.err.print(" 3"); >System.err.print(" 4"); > > >> 0 3 >> RUNTIME ERROR: Exception in thread "main" java.lang.RuntimeException 

Не заходим в catch, заходим в finally, не продолжаем после оператора — вылетаем с неперехваченным исключением

9. Вложенные try + catch + finally

Операторы обычно допускают неограниченное вложение.
Пример с if

public class App < public static void main(String[] args) < if (args.length >1) < if (args.length >2) < if (args.length >3) < . >> > > > 
public class App < public static void main(String[] args) < for (int i = 0; i < 10; i++) < for (int j = 0; j < 10; i++) < for (int k = 0; k < 10; k++) < . >> > > > 

Суть в том, что try-cacth-finally тоже допускает неограниченное вложение.
Например вот так

public class App < public static void main(String[] args) < try < try < try < . >catch (Exception e) < >finally <> > catch (Exception e) < >finally <> > catch (Exception e) < >finally <> > > 

Или даже вот так

public class App < public static void main(String[] args) < try < try < . >catch (Exception e) < . >finally < . >> catch (Exception e) < try < . >catch (Exception e) < . >finally < . >> finally < try < . >catch (Exception e) < . >finally < . >> > > 

Ну что же, давайте исследуем как это работает.

Вложенный try-catch-finally без исключения

public class App < public static void main(String[] args) < try < System.err.print(" 0"); try < System.err.print(" 1"); // НИЧЕГО System.err.print(" 2"); >catch (RuntimeException e) < System.err.print(" 3"); // НЕ заходим - нет исключения >finally < System.err.print(" 4"); // заходим всегда >System.err.print(" 5"); // заходим - выполнение в норме > catch (Exception e) < System.err.print(" 6"); // НЕ заходим - нет исключения >finally < System.err.print(" 7"); // заходим всегда >System.err.print(" 8"); // заходим - выполнение в норме > > >> 0 1 2 4 5 7 8 

Мы НЕ заходим в обе catch-секции (нет исключения), заходим в обе finally-секции и выполняем обе строки ПОСЛЕ finally.

Вложенный try-catch-finally с исключением, которое ПЕРЕХВАТИТ ВНУТРЕННИЙ catch

public class App < public static void main(String[] args) < try < System.err.print(" 0"); try < System.err.print(" 1"); if (true) System.err.print(" 2"); > catch (RuntimeException e) < System.err.print(" 3"); // ЗАХОДИМ - есть исключение >finally < System.err.print(" 4"); // заходим всегда >System.err.print(" 5"); // заходим - выполнение УЖЕ в норме > catch (Exception e) < System.err.print(" 6"); // не заходим - нет исключения, УЖЕ перехвачено >finally < System.err.print(" 7"); // заходим всегда >System.err.print(" 8"); // заходим - выполнение УЖЕ в норме > > >> 0 1 3 4 5 7 8 

Мы заходим в ПЕРВУЮ catch-секцию (печатаем «3»), но НЕ заходим во ВТОРУЮ catch-секцию (НЕ печатаем «6», так как исключение УЖЕ перехвачено первым catch), заходим в обе finally-секции (печатаем «4» и «7»), в обоих случаях выполняем код после finally (печатаем «5»и «8», так как исключение остановлено еще первым catch).

Вложенный try-catch-finally с исключением, которое ПЕРЕХВАТИТ ВНЕШНИЙ catch

public class App < public static void main(String[] args) < try < System.err.print(" 0"); try < System.err.print(" 1"); if (true) System.err.print(" 2"); > catch (RuntimeException e) < System.err.print(" 3"); // НЕ заходим - есть исключение, но НЕПОДХОДЯЩЕГО ТИПА >finally < System.err.print(" 4"); // заходим всегда >System.err.print(" 5"); // не заходим - выполнение НЕ в норме > catch (Exception e) < System.err.print(" 6"); // ЗАХОДИМ - есть подходящее исключение >finally < System.err.print(" 7"); // заходим всегда >System.err.print(" 8"); // заходим - выполнение УЖЕ в норме > > >> 0 1 4 6 7 8 

Мы НЕ заходим в ПЕРВУЮ catch-секцию (не печатаем «3»), но заходим в ВТОРУЮ catch-секцию (печатаем «6»), заходим в обе finally-секции (печатаем «4» и «7»), в ПЕРВОМ случае НЕ выполняем код ПОСЛЕ finally (не печатаем «5», так как исключение НЕ остановлено), во ВТОРОМ случае выполняем код после finally (печатаем «8», так как исключение остановлено).

Вложенный try-catch-finally с исключением, которое НИКТО НЕ ПЕРЕХВАТИТ

public class App < public static void main(String[] args) < try < System.err.print(" 0"); try < System.err.print(" 1"); if (true) System.err.print(" 2"); > catch (RuntimeException e) < System.err.print(" 3"); // НЕ заходим - есть исключение, но НЕПОДХОДЯЩЕГО ТИПА >finally < System.err.print(" 4"); // заходим всегда >System.err.print(" 5"); // НЕ заходим - выполнение НЕ в норме > catch (Exception e) < System.err.print(" 6"); // не заходим - есть исключение, но НЕПОДХОДЯЩЕГО ТИПА >finally < System.err.print(" 7"); // заходим всегда >System.err.print(" 8"); // не заходим - выполнение НЕ в норме > > >> 0 1 4 7 >> RUNTIME EXCEPTION: Exception in thread "main" java.lang.Error 

Мы НЕ заходим в ОБЕ catch-секции (не печатаем «3» и «6»), заходим в обе finally-секции (печатаем «4» и «7») и в обоих случаях НЕ выполняем код ПОСЛЕ finally (не печатаем «5» и «8», так как исключение НЕ остановлено), выполнение метода прерывается по исключению.

Контакты

Я занимаюсь онлайн обучением Java (вот курсы программирования) и публикую часть учебных материалов в рамках переработки курса Java Core. Видеозаписи лекций в аудитории Вы можете увидеть на youtube-канале, возможно, видео канала лучше систематизировано в этой статье.

  1. показываю различные варианты применения
  2. строю усложняющуюся последовательность примеров по каждому варианту
  3. объясняю логику двигавшую авторами (по мере возможности)
  4. даю большое количество тестов (50-100) всесторонне проверяющее понимание и демонстрирующих различные комбинации
  5. даю лабораторные для самостоятельной работы

skype: GolovachCourses
email: GolovachCourses@gmail.com

  • java
  • exception
  • исключения
  • курсы программирования

Книги по Java и Eclipse / Java / Java.Промышленное программирование

helper.readFromConsole(); > > В ответ на запрос можно ввести некоторые данные и получить следующий результат: Введите числовой код: 1001 Введите пароль: **** Код доступа: 1001 Пароль: pass При вводе значения code , не являющегося цифрой, на экран будет выдано сообщение об ошибке при попытке его преобразования в целое число, так как метод valueOf() пытается преобразовать строку в целое число, не проверив предварительно, может ли быть выполнено это преобразование. Класс Scanner Объект класса java.util.Scanner принимает форматированный объект (ввод) и преобразует его в двоичное представление. При вводе могут использоваться данные из консоли, файла, строки или любого другого источника, реали- зующего интерфейсы Readable или ReadableByteChannel . Класс определяет следующие конструкторы: Scanner(File source) throws FileNotFoundException Scanner(File source, String charset) throws FileNotFoundException Scanner(InputStream source) Scanner(InputStream source, String charset) Scanner(Readable source) Scanner(ReadableByteChannel source) Scanner(ReadableByteChannel source, String charset) Scanner(String source) , где source – источник входных данных, а charset – кодировка. Объект класса Scanner читает лексемы из источника, указанного в конструкторе, например из строки или файла. Лексема – это набор данных, выделенный набором разделителей (по умолчанию пробелами). В случае ввода из консоли следует определить объект: Scanner con = new Scanner(System.in); После создания объекта его используют для ввода, например целых чисел, следующим образом: write(con.hasNextInt()) < int n = con.nextInt(); >В классе Scanner определены группы методов, проверяющих данные заданного типа на доступ для ввода. Для проверки наличия произвольной лексемы используется метод hasNext() . Проверка конкретного типа производится с помощью одного из методов boolean hasNext Тип () или boolean

hasNext Тип (int radix) , где radix – основание системы счисления. Например, вызов метода hasNextInt() возвращает true , только если следующая входящая лексема – целое число. Если данные указанного типа доступны, они считываются с помощью одного из методов Тип next Тип () . Произвольная лексема считывается методом String next() . После извлечения любой лексемы текущий указатель устанавливается перед следующей лексемой. // пример # 10 : разбор файла: ScannerLogic.java : ScannerDemo.java package chap09; import java.io.*; import java.util.Scanner; class ScannerLogic < static String filename = "scan.txt"; public static void scanFile() < try < FileReader fr = new FileReader(filename); Scanner scan = new Scanner(fr); while (scan.hasNext()) < //чтение из файла if (scan.hasNextInt()) System. out .println( scan.nextInt() + ":int"); else if (scan.hasNextDouble()) System. out .println( scan.nextDouble() + ":double"); else if (scan.hasNextBoolean()) System. out .println( scan.nextBoolean() + ":boolean"); else System. out .println( scan.next() + ":String"); >> catch (FileNotFoundException e) < System. err .println(e); >> public static void makeFile() < try < FileWriter fw = new FileWriter(filename); //создание потока для записи fw.write("2 Java 1,5 true 1.6 "); //запись данных fw.close(); >catch (IOException e) < System. err .println(e); >>

> public class ScannerDemo < public static void main(String[] args) < ScannerLogic. makeFile (); ScannerLogic. scanFile (); >> В результате выполнения программы будет выведено: 2:int Java:String 1.5:double true:boolean 1.6:String Процедура проверки типа реализована при с помощью методов hasNext Тип () . Такой подход предпочтителен из-за отсутствия возможности возникновения исключительной ситуации, так как ее обработка требует на порядок больше ресурсов, чем нормальное течение программы. Для чтения строки из потока ввода применяются методы next() или nextLine() . Объект класса Scanner определяет границы лексемы, основываясь на наборе разделителей. Можно задавать разделители с помощью метода useDelimiter(Pattern pattern) или useDelimiter(String pattern) , где pattern содержит набор разделителей. /* пример # 11 : применение разделителей: ScannerDelimiterDemo.java*/ package chapt09; import java.util.Scanner; public class ScannerDelimiterDemo < public static void main(String args[]) < double sum = 0.0; Scanner scan = new Scanner("1,3;2,0; 8,5; 4,8; 9,0; 1; 10"); scan.useDelimiter(";\\s*"); while (scan.hasNext()) < if (scan.hasNextDouble()) sum += scan.nextDouble(); else System. out .println(scan.next()); >System. out .printf("Сумма чисел p107 ft37">> > > В результате выполнения программы будет выведено: Сумма чисел = 36.6 Использование шаблона "; *" указывает объекту класса Scanner , что ‘ ; ’ и ноль или более пробелов следует рассмативать как разделитель.

Метод String findInLine(Pattern pattern) или String findInLine(String pattern) ищет заданный шаблон в следующей строке текста. Если шаблон найден, соответствующая ему подстрока извлекается из строки ввода. Если совпадений не найдено, то возвращается null . Методы String findWithinHorizon(Pattern pattern, int count) и String findWithinHorizon(String pattern, int count) производят поиск заданного шаблона в ближайших count символах. Можно пропустить образец с помощью метода skip(Pattern pattern) . Если в строке ввода найдена подстрока, соответствующая образцу pattern , метод skip() просто перемещается за нее в строке ввода и возвращает ссылку на вызывающий объект. Если подстрока не найдена, метод skip() генерирует ис- ключение NoSuchElementException . Архивация Для хранения классов языка Java и связанных с ними ресурсов в языке Java используются сжатые архивные jar -файлы. Для работы с архивами в спецификации Java существуют два пакета – java.util.zip и java.util.jar соответственно для архивов zip и jar . Различие форматов jar и zip заключается только в расширении архива zip. Пакет java.util.jar аналогичен пакету java.util.zip , за исключением реализации конструкторов и метода void putNextEntry(ZipEntry e) класса JarOutputStream . Ниже будет рассмотрен только пакет java.util.jar . Чтобы переделать все примеры на использование zip -архива, достаточно всюду в коде заменить Jar на Zip . Пакет java.util.jar позволяет считывать, создавать и изменять файлы форматов jar , а также вычислять контрольные суммы входящих потоков данных. Класс JarEntry (подкласс ZipEntry ) используется для предоставления доступа к записям jar -файла. Наиболее важными методами класса являются: void setMethod(int method) – устанавливает метод сжатия записи; int getMethod() – возвращает метод сжатия записи; void setComment(String comment) – устанавливает комментарий за- писи; String getComment() – возвращает комментарий записи; void setSize(long size) – устанавливает размер несжатой записи; long getSize() – возвращает размер несжатой записи; long getCompressedSize() – возвращает размер сжатой записи; У класса JarOutputStream существует возможность записи данных в поток вывода в jar -формате. Он переопределяет метод write() таким образом, чтобы любые данные, записываемые в поток, предварительно сжимались. Основными методами данного класса являются: void setLevel(int level) – устанавливает уровень сжатия. Чем больше уровень сжатия, тем медленней происходит работа с таким файлом;

void putNextEntry(ZipEntry e) – записывает в поток новую jar - запись. Этот метод переписывает данные из экземпляра JarEntry в поток вывода; void closeEntry() – завершает запись в поток jar -записи и заносит дополнительную информацию о ней в поток вывода; void write(byte b[], int off, int len) – записывает данные из буфера b начиная с позиции off длиной len в поток вывода; void finish() – завершает запись данных jar -файла в поток вывода без закрытия потока; void close() – закрывает поток записи. /* пример # 12 : создание jar-архива: PackJar.java */ package chapt09; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import java.util.zip.Deflater; public class PackJar < public static void pack(String[] filesToJar, String jarFileName, byte [] buffer) < try < JarOutputStream jos = new JarOutputStream( new FileOutputStream(jarFileName)); // метод сжатия jos.setLevel(Deflater. DEFAULT_COMPRESSION ); for ( int i = 0; i < filesToJar.length; i++) < System. out .println(i); jos.putNextEntry( new JarEntry(filesToJar[i])); FileInputStream in = new FileInputStream(filesToJar[i]); int len; while ((len = in.read(buffer)) >0) jos.write(buffer, 0, len); jos.closeEntry(); in.close(); > jos.close(); > catch (IllegalArgumentException e) < e.printStackTrace(); System. err .println("Некорректный аргумент"); >catch (FileNotFoundException e) < e.printStackTrace();

System. err .println("Файл не найден"); > catch (IOException e) < e.printStackTrace(); System. err .println("Ошибка доступа"); >> public static void main(String[] args) < System. out .println("Создание jar-архива"); // массив файлов для сжатия String[] filesToJar = new String[2]; filesToJar[0] = "chapt09//UseJar.java"; filesToJar[1] = "chapt09//UseJar.class"; byte [] buffer = new byte [1024]; // имя полученного архива String jarFileName = "example.jar"; pack (filesToJar, jarFileName, buffer); >> Класс JarFile обеспечивает гибкий доступ к записям, хранящимся в jar - файле. Это очень эффективный способ, поскольку доступ к данным осуществляется гораздо быстрее, чем при считывании каждой отдельной записи. Единственным недостатком является то, что доступ может осуществляться только для чтения. Метод entries () извлекает все записи из jar -файла. Этот метод возвращает список экземпляров JarEntry – по одной для каждой записи в jar - файле. Метод getEntry(String name) извлекает запись по имени. Метод getInputStream() создает поток ввода для записи. Этот метод возвращает поток ввода, который может использоваться приложением для чтения данных записи. Класс JarInputStream читает данные в jar -формате из потока ввода. Он переопределяет метод read() таким образом, чтобы любые данные, считываемые из потока, предварительно распаковывались. /* пример # 13 : чтение jar-архива: UnPackJar.java */ package chapt09; import java.io.*; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class UnPackJar < private File destFile; // размер буфера для распаковки public final int BUFFER = 2048; public void unpack(String destinationDirectory, String nameJar) < File sourceJarFile = new File(nameJar); try < File unzipDestinationDirectory =

public static void main(String[] args) < System. out .println( "Извлечение данных из jar-архива"); // расположение и имя архива String nameJar = "c:\\work\\example.jar"; // куда файлы будут распакованы String destination = "c:\\temp\\"; new UnPackJar().unpack(destination, nameJar); >> Задания к главе 9 Вариант A В следующих заданиях требуется ввести последовательность строк из текстового потока и выполнить указанные действия. При этом могут рассматриваться два варианта: каждая строка состоит из одного слова; каждая строка состоит из нескольких слов. Имена входного и выходного файлов, а также абсолютный путь к ним могут быть введены как параметры командной строки или храниться в файле. 1. В каждой строке найти и удалить заданную подстроку. 2. В каждой строке стихотворения Александра Блока найти и заменить заданную подстроку на подстроку иной длины. 3. В каждой строке найти слова, начинающиеся с гласной буквы. 4. Найти и вывести слова текста, для которых последняя буква одного слова совпадает с первой буквой следующего слова. 5. Найти в строке наибольшее число цифр, идущих подряд. 6. В каждой строке стихотворения Сергея Есенина подсчитать частоту повторяемости каждого слова из заданного списка и вывести эти слова в порядке возрастания частоты повторяемости. 7. В каждом слове сонета Вильяма Шекспира заменить первую букву слова на прописную. 8. Определить частоту повторяемости букв и слов в стихотворении Александра Пушкина. Вариант B Выполнить задания из варианта B главы 4, сохраняя объекты приложения в одном или нескольких файлах с применением механизма сериализации. Объекты могут содержать поля, помеченные как static , а также transient . Для изменения информации и извлечения информации в файле создать специальный классконнектор с необходимыми для выполнения этих задач методами. Вариант С При выполнении следующих заданий для вывода результатов создавать новую директорию и файл средствами класса File . 1. Создать и заполнить файл случайными целыми числами. Отсортировать содержимое файла по возрастанию.

2. Прочитать текст Java-программы и все слова public в объявлении атрибутов и методов класса заменить на слово private . 3. Прочитать текст Java-программы и записать в другой файл в обратном порядке символы каждой строки. 4. Прочитать текст Java-программы и в каждом слове длиннее двух символов все строчные символы заменить прописными. 5. В файле, содержащем фамилии студентов и их оценки, записать прописными буквами фамилии тех студентов, которые имеют средний балл более “7”. 6. Файл содержит символы, слова, целые числа и числа с плавающей запятой. Определить все данные, тип которых вводится из командной строки. 7. Из файла удалить все слова, содержащие от трех до пяти символов, но при этом из каждой строки должно быть удалено только максимальное четное количество таких слов. 8. Прочитать текст Java-программы и удалить из него все “лишние” пробелы и табуляции, оставив только необходимые для разделения операторов. 9. Из текста Java-программы удалить все виды комментариев. 10. Прочитать строки из файла и поменять местами первое и последнее слова в каждой строке. 11. Ввести из текстового файла, связанного с входным потоком, последовательность строк. Выбрать и сохранить m последних слов в каждой из последних n строк. 12. Из текстового файла ввести последовательность строк. Выделить отдельные слова, разделяемые пробелами. Написать метод поиска слова по образцу-шаблону. Вывести найденное слово в другой файл. 13. Сохранить в файл, связанный с выходным потоком, записи о телефонах и их владельцах. Вывести в файл записи, телефоны которых начинаются на k и на j. 14. Входной файл содержит совокупность строк. Строка файла содержит строку квадратной матрицы. Ввести матрицу в двумерный массив (размер матрицы найти). Вывести исходную матрицу и результат ее транспонирования. 15. Входной файл хранит квадратную матрицу по принципу: строка представляет собой число. Определить размерность. Построить 2-мерный массив, содержащий матрицу. Вывести исходную матрицу и результат ее поворота на 90 градусов по часовой стрелке. 16. В файле содержится совокупность строк. Найти номера строк, совпадающих с заданной строкой. Имя файла и строка для поиска – аргументы командной строки. Вывести строки файла и номера строк, совпадающих с заданной.

Тестовые задания к главе 9 Вопрос 9.1. Можно ли изменить корневой каталог, в который вкладываются все пользовательские каталоги, используя объект myfile класса File ? Если это возможно, то с помощью какой инструкции? 1) myfile.chdir("NAME"); 2) myfile.cd("NAME"); 3) myfile.changeDir("NAME"); 4) методы класса File не могут изменять корневой каталог. Вопрос 9.2. Экземпляром какого класса является поле System.in ? 1) java.lang.System; 2) java.io.InputStream; 3) java.io.BufferedInputStream; 4) java.io.PrintStream; 5) java.io.Reader. Вопрос 9.3. Какие из следующих операций можно выполнить применительно к файлу на диске с помощью методов объекта класса File ? 1) добавить запись в файл; 2) вернуть имя родительской директории; 3) удалить файл; 4) определить, текстовую или двоичную информацию содержит файл. Вопрос 9.4. Какой абстрактный класс является суперклассом для всех классов, используемых для чтения байтов? 1) Reader; 2) FileReader; 3) ByteReader; 4) InputStream; 5) FileInputStream. Вопрос 9.5. При объявлении какого из приведенных понятий может быть использован модификатор transient ? 1) класса; 2) метода; 3) поля класса; 4) локальной переменной; 5) интерфейса.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *