Управление выполнением программы
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Управление в Java почти идентично средствам, используемым в С и C++.

Условные операторы

If-else

В обобщенной форме этот оператор записывается следующим образом:

if (логическое выражение) оператор1; [ else оператор2;]

Раздел else необязателен. На месте любого из операторов может стоять составной оператор, заключенный в фигурные скобки. Логическое выражение - это любое выражение, возвращающее значение типа boolean.

Ниже приведена программа, в которой для определения, к какому времени года относится тот или иной месяц, используются операторы if-else.

class IfElse {

public static void main(String[] args) {

              int month = 4;

     String season;

     if (month == 12 || month == 1 || month == 2) {

           season = "Winter";

     }

    else if (month ==3 || month == 4 || month == 5) {

               season = "Spring";

       }

       else if (month == 6 || month == 7 || month == 8) {

              season = "Summer";

        }

        else if (month == 9 || month == 10 || month == 11) {

               season = "Autumn";

        }

        else {season = "Bogus Month";}

        System.out.println( "April is in the " + season + ".");

}

}

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

April is in the Spring.

Break

В языке Java отсутствует оператор goto. Для того, чтобы в некоторых случаях заменять goto, в Java предусмотрен оператор break. Этот оператор сообщает исполняющей среде, что следует прекратить выполнение блока и передать управление оператору, следующему за данным блоком. Для именования блоков в языке Java используются метки. Оператор break при работе с циклами и в операторах switch может использоваться без метки. В таком случае подразумевается выход из текущего блока.

Например, в следующей программе имеется три вложенных блока, и у каждого своя уникальная метка. Оператор break, стоящий во внутреннем блоке, вызывает переход на оператор, следующий за блоком b. При этом пропускаются два оператора println.

class Break {

public static void main(String[] args) {

      boolean t = true;

      a: { b:    { c:        {

     System.out.println("Before the break"); // Перед break

    if (t)

   break b;

  System.out.println("This won't execute");

  // He будет выполнено

  }

  System.out.println("This won't execute");

  // He будет выполнено

  }

  System.out.println("This is after b");

  //После b 

}

}

}

В результате исполнения программы вы получите следующий результат:

Before the break

This is after b

Switch

Оператор switch обеспечивает ясный способ переключения между различными частями программного кода в зависимости от значения одной переменной или выражения. Общая форма этого оператора такова:

switch ( выражение ) { case значение1:

      break;

case значение2:

      break;

case значение m:

      break;

default:

}

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

Если же значению выражения не соответствует ни один из операторов case, управление передается коду, расположенному после ключевого слова default. Отметим, что оператор default необязателен. В случае, когда ни один из операторов case не соответствует значению выражения и в switch отсутствует оператор default выполнение программы продолжается с оператора, следующего за оператором switch.

Внутри оператора switch (а также внутри циклических конструкций, но об этом - позже) break без метки приводит к передаче управления на код, стоящий после оператора switch. Если break отсутствует, после текущего раздела case будет выполняться следующий. Иногда бывает удобно иметь в операторе switch несколько смежных разделов case, не разделенных оператором break.

class SwitchSeason {

public static void main(String[] args) {

       int month = 4;

       String season;

       switch (month) {

            case 12: // проходит дальше

            case 1: // проходит дальше

            case 2:

                 season = "Winter";

            break;

            case 3: // проходит дальше

            case 4: // проходит дальше

           case 5:

                season = "Spring";

           break ;

           case 6: // проходит дальше

         case 7: // проходит дальше

           case 8:

                season = "Summer";

            break;

            case 9: // проходит дальше

            case 10: // проходит дальше

            case 11:

                 season = "Autumn";

            break;

            default:

                 season = "Bogus Month";

             }

            System.out.println("April is in the " + season + ".");

}

}

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

class WordCount {

static String text = "Now is the tifne\n" +

                "for all good men\n" +

                "to come to the aid\n" +

                "of their country\n"+

                "and pay their due taxes\n";

static int len = text.length();

public static void main(String[] args) {

     boolean inWord = false;

     int numChars = 0;

    int numWords = 0;

   int numLines = 0;

   for (int i=0; i < len; i++) {

        char с = text.charAt(i);

          numChars++;

          switch ( с ) {

             case '\n': numLines++; // проходит дальше

             case '\t': // проходит дальше

             case ' ' : if (inWord) {

                   numWords++;

                  inWord = false;

             }

             break;

             default: inWord = true;

       }

   }

   System.out.println("\t" + numLines +"\t" +

  numWords + "\t" + numChars);

}

}

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

5   21   94

Return

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

class ReturnDemo {

public static void main(String[] args) {

      boolean t = true;

     System.out.println("Before the return");

     // Перед оператором return

     if (t) return;

     System.out.println("This won't execute");

    //Это не будет выполнено

}

}

Замечание

Зачем в этом примере использован оператор if (t)? Дело в том, не будь этого оператора, транслятор Java догадался бы, что последний оператор println никогда не будет выполнен. Такие случаи в Java считаются ошибками, поэтому без оператора if оттранслировать этот пример нам бы не удалось.

Циклы

Любой цикл можно разделить на 4 части - инициализацию, тело, итерацию и условие завершения. В Java есть три циклические конструкции: while (с предусловием), do-while (с постусловием) и for (с параметром).

While

Этот цикл многократно выполняется до тех пор, пока значение логического выражения равно true. Ниже приведена общая форма оператора while:

[ инициализация; ]

while ( завершение ) {

  тело;

  [итерация;] }

Инициализация и итерация необязательны. Ниже приведен пример цикла while для печати десяти строк.

class WhileDemo {

public static void main(String[] args) {

     int n = 10;

     while (n > 0) {

           System.out.println("tick " + n);

      n--;

    }

}

}

Do-while

Иногда возникает потребность выполнить тело цикла, по крайней мере, один раз - даже в том случае, когда логическое выражение с самого начала принимает значение false. Для таких случаев в Java используется циклическая конструкция do-while. Её общая форма записи такова:

[ инициализация; ] do { тело; [итерация;] } while

( завершение );

В следующем примере тело цикла выполняется до первой проверки условия завершения. Это позволяет совместить код итерации с условием завершения:

class DoWhile {

public static void main(String[] args) {

     int n = 10;

     do {

          System.out.println("tick " + n);

     } while (--n < 0);

}

}

For

В этом операторе предусмотрены места для всех четырех частей цикла. Ниже приведена общая форма оператора записи for.

for ( инициализация; завершение; итерация ) тело;

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

class ForDemo {

public static void main(String[] args) {

       for (int i = 1; i <= 10; i++)

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

}

}

Следующий пример - вариант программы, ведущей обратный отсчет.

class ForTick {

public static void main(String[] args) {

      for ( int n = 10; n > 0; n --)

           System . out . println (" tick " + n );

}

}

Обратите внимание - переменные можно объявлять внутри раздела инициализации оператора for. Переменная, объявленная внутри оператора for, действует в пределах этого оператора.

А вот - новая версия примера с временами года, в которой используется оператор for.

class Months {

static String months[] = {

    "January", "February", "March", "April",

    "May", "June", "July", "August", "September",

    "October", "November", "December" };

static int monthdays[] = { 31, 28, 31, 30, 31,

     30, 31, 31, 30, 31, 30, 31 };

static String spring = "spring";

static String summer = "summer";

static String autumn = "autumn";

static String winter = "winter";

static String seasons[] = { winter, winter, spring,

     spring, spring, summer, summer,

     summer, autumn, autumn, autumn,

     winter };

public static void main(String[] args) {

      for (int month = 0; month < 12; month++) {

           System.out.println(months[month] + " is a " +

           seasons[month] + " month with " +

           monthdays[month] + " days.");

       }

 }

}

При выполнении эта программа выводит следующие строки:

January is a winter month with 31 days.

February is a winter month with 28 days.

March is a spring month with 31 days.

April is a spring month with 30 days.

May is a spring month with 31 days.

June is a summer month with 30 days.

July is a summer month with 31 days.

August is a summer month with 31 days.

September is a autumn month with 30 days.

October is a autumn month with 31 days.

November is a autumn month with 30 days.

December a winter month with 31 days.

Оператор запятая

Иногда возникают ситуации, когда разделы инициализации или итерации цикла for требуют нескольких операторов. Поскольку составной оператор в фигурных скобках в заголовок цикла for вставлять нельзя, Java предоставляет альтернативный путь. Применение запятой (,) для разделения нескольких операторов допускается только внутри круглых скобок оператора for. Ниже приведен тривиальный пример цикла for, в котором в разделах инициализации и итерации стоит несколько операторов.

class Comma {

public static void main(String[] args) {

    int a, b;

   for (a = 1, b = 4; a < b; a++, b--) {

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

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

  }

}

}

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

а = 1

b = 4

а = 2

b = 3

Continue

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

class ContinueDemo {

public static void main(String args[]) {

     for (int i=0; i < 10; i++) {

          System.out.print(i + " ");

          if (i % 2 == 0) continue;

         System.out.println("");

}

}

}

Если индекс четный, цикл продолжается без вывода символа новой строки. Результат выполнения этой программы таков:

0 1

2 3

4 5

6 7

8 9

Как и в случае оператора break, в операторе continue можно задавать метку, указывающую, в каком из вложенных циклов вы хотите досрочно прекратить выполнение текущей итерации. Для иллюстрации служит программа, использующая оператор continue с меткой для вывода треугольной таблицы умножения для чисел от 0 до 9:

class ContinueLabel {

public static void main(String[] args) {

      outer: for (int i=0; i < 10; i++) {

           for (int j = 0; j < 10; j++) {

                   if (j > i) {

                    System.out.println("");

                    continue outer;

             }

                 System.out.print(" " + (i * j));

           }

      }

}

}

Оператор continue в этой программе приводит к завершению внутреннего цикла со счетчиком j и переходу к очередной итерации внешнего цикла со счетчиком i. В процессе работы эта программа выводит следующие строки:

0

0 1

0 2 4

0 3 6 9

0 4 8 12 16

0 5 10 15 20 25

0 6 12 18 24 30 36

0 7 14 21 28 35 42 49

0 8 16 24 32 40 48 56 64

0 9 18 27 36 45 54 63 72 81

Исключения

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

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

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

Исключение выбрасывается (throw), если в процессе выполнения кода встречается неожиданная ошибочная ситуация. Затем исключение отлавливается (catch) соответствующим блоком кода. Исключения, не подвергшиеся обработке, приводят к завершению потока вычислений, но прежде соответствующему объекту класса ThreadGroup предоставляется возможность наиболее приемлемым в конкретной ситуации способом «управиться» с исключением – чаще всего речь идет только о выводе на экран полезной информации об обстоятельствах происшедшего и источнике ошибки (в терминах позиций стека вызовов). Начиная с 6 версии Java это не так: механизм логирования ошибок может быть произвольным.

Исключения – это объекты. На рисунке 3 показано, как выглядят несколько верхних уровней иерархии типов исключений Java.

Все типы исключений должны наследовать класс Throwable или один из классов, производных от него. Класс Throwable содержит поле типа String, предназначенное для хранения информации об исключении. Обычно новые типы исключений создаются на основе класса Exception, производного от Throwable.

Исполняющая система способна выбрасывать объекты исключений двух основных семейств типов – производных от RuntimeException либо расширяющих класс ошибок Error. Эти исключения относятся к категории необъявляемых.

Рисунок 3

Исключения типов Error свидетельствуют о весьма серьёзных ошибках, которые не могут быть отловлены (либо допускают такую возможность в редких случаях и с немалым трудом), а их последствия, как правило, не поддаются преодолению. Типы Error не являются наследниками класса RuntimeException, так что даже если вы и вознамеритесь предусмотреть предложения catch для поимки всех исключений Exception или RuntimeException (что зачастую нельзя считать хорошим решением), исключения Error всё равно от вас «ускользнут». Предложения finally конструкции try, разумеется, выполняются при возникновении любых исключений – в том числе и Error, так что программа всегда сможет выполнить некоторый набор необходимых завершающих операций.

С формальной точки зрения вполне допустимо расширять классы RuntimeException или Error с целью создания собственных необъявляемых исключений, т.е. таких исключений, которые могут быть сгенерированы без предварительного объявления их в предложении throws. Уместность наследования от того или иного класса исключений определяется исходя из логики объявляемых и необъявляемых исключений. Вам надлежит знать об этом шансе по единственной причине – реализовывать его на практике как раз не следует. Предложение throws предназначено именно для того, чтобы облегчить восприятие метода теми, кто будет им пользоваться. Расширение типов RuntimeException или Error и использование их объектов в методах конкретных классов свидетельствует о неверном понимании механизмов обработки исключений и затрудняет практическое применение методов программистами, которые вправе надеяться на наличие исчерпывающего описания набора возможных исключений в составе предложения throws.

Большинство типов RuntimeException и Error поддерживает, самое меньшее, по два конструктора: первый не предусматривает задания параметров, а второй в качестве параметра принимает объект String с содержательным описанием природы ошибки. Строка описания может быть получена с помощью метода getMessage.

Примеры классов, наследующих от RuntimeException

ArithmeticException extends RuntimeException

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

IndexOutOfBoundsException extends RuntimeException

Задано значение индекса массива или содержимого строки типа String, не принадлежащее допустимому диапазону.

Примеры классов , наследующих от Error

AbstractMethodError extends IncompatibleClassChangeError

Вызван абстрактный метод класса, не содержащий реализации.

IncompatibleClassChangeError extends LinkageError

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

LinkageError extends Error

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

Говоря об исключениях, мы будем иметь в виду преимущественно объявляемые исключения. В случае применения объявляемых исключений компилятор получает возможность проверить, действительно ли метод генерирует только те исключения, которые обнародованы в его объявлении. Все исключения классов, наследующих Exception, относятся к категории объявляемых. Исключения времени выполнения и объекты ошибок классов RuntimeException, Error и производных от них принадлежат к группе необъявляемых исключений.

Объявляемые исключения служат для представления ситуаций, которые, несмотря на их «исключительный» характер, вполне предсказуемы, и поскольку они происходят, с ними необходимо уметь обращаться. Объявляя исключения, мы тем самым документально признаем возможность их возникновения и вынуждаем пользователя кода предпринимать соответствующие меры для устранения их последствий. Необъявляемые исключения отражают события, которые связаны с ошибками в логике кода и поэтому не могут быть успешно преодолены во время выполнения программы. Например, исключение типа IndexOutOfBoundsException, генерируемое при попытке доступа к элементу массива с неверным значением индекса, уведомляет вас о том, что программа некорректно вычисляет индекс или неправильно проверяет значение, используемое в качестве индекса. Ошибки такого рода должны быть исправлены в исходном коде программы. Если принять во внимание, что ошибку легко допустить в любой строке кода, то будет неразумно пытаться объявлять и отлавливать все исключения, поэтому многие из них и остаются в категории «необъявляемых».

Иногда бывает полезно иметь в своем распоряжении более полную информацию о природе ошибке, не только ту единственную строку текста, которая предусмотрена классом Exception. В таких случаях класс Exception может быть расширен с добавлением недостающих элементов данных, которые обычно передаются конструктору в виде аргументов (см. пример 20).

Предположим, что у нас есть метод, который выполняет замещение текущего значения указанного атрибута новым. Если атрибут с заданным именем не существует, следует предусмотреть действия по выбрасыванию соответствующего исключения, так как вполне резонно полагать, что метод способен иметь дело только с существующими атрибутами. Желательно, чтобы объект исключения располагал наименованием атрибута, виновного в происшедшем. Рассмотрим объявление класса NoSuchAttributeException, помогающего решить задачу:

Пример 20.

public class NoSuchAttributeException extends Exception {

public String attrName;

public NoSuchAttributeException(String name) {

       super (“Атрибут с именем \”” + name + “/” не найден“);

       attrName = name;

}

}

В состав класса NoSuchAttributeException, производного от Exception, добавлены конструктор, принимающий в качестве параметра строку наименования атрибута, и public-поле, предназначенное для ее хранения. В теле конструктора вызывается конструктор базового класса, которому передается строка описания ошибки. С точки зрения кода, выполняющего обработку ошибок, рассмотренный тип исключений достаточно полезен, так как он содержит и внятное описание ошибки, и наименование атрибута, отсутствие которого привело к ее возникновению.

Возможность добавления данных – это только один довод в пользу создания новых типов исключений. Другой, не менее важный, связан с тем, что тип исключения как таковой – это неотъемлемая часть информации об ошибке, поскольку исключения «отлавливаются» в соответствии с их типами. По этой причине класс NoSuchAttributeException стоило создать даже в том случае, если бы нам и не требовались дополнительные поля данных. Вообще говоря, новый тип исключений целесообразно создавать в тех случаях, когда желательно приобрести возможность «отлова» одних исключений, игнорируя при этом другие.

Throw

Исключения выбрасываются (генерируются) инструкцией throw:

throw Выражение;

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

Пример 21.

public void replaceValue(String name, Object newValue) throws NoSuchAttributeException

{

Attr attr = find(name);

if (attr == null) throw new NoSuchAttributeException(name);

attr.setValue(newValue);

}

В теле метода replaceValue сначала вызывается метод, выполняющий поиск атрибута по заданному имени. Если результат поиска отрицателен, объект исключения типа NoSuchAttributeException вначале создается, с передачей его конструктору строки имени атрибута, а затем выбрасывается. (Исключение – это объект, поэтому, прежде всего, его следует явно создать). Если же атрибут с указанным именем существует, его текущее значение заменяется новым. Исключение может быть сгенерировано также косвенным образом при вызове метода, который способен его выбрасывать.

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

Если исключение возникло, все действия, предусмотренные в программном коде после инструкции или выражения, вызвавших исключение, далее не выполняются. Если исключение было выброшено в процессе вычисления левостороннего операнда выражения, никакие составляющие правостороннего операнда больше не анализируются. Аналогично, если появление исключения спровоцировал левый аргумент в любой части выражения, все аргументы справа от него игнорируются. Следующим будет выполнен либо «завершающий» блок finally, либо блок catch, обрабатывающий исключение.

Результатом работы инструкции throw служит синхронное ( synchronous ) исключение – то же самое происходит, например, при целочисленном делении на нуль: исключение возникает как непосредственный итог выполнения определенной инструкции, причем неважно, выбрасывается ли оно явно, командой throw, либо косвенно, исполняющей системой, обнаружившей факт деления на нуль. Асинхронное ( asynchronous ) исключение может возникнуть внезапно, независимо от того, какая именно инструкция прикладной программы выполняется в данный момент.

Асинхронные исключения проявляются в двух ситуациях. Первая связана с внутренними ошибками виртуальной машины Java – такие исключения считаются асинхронными, поскольку их появление провоцируется кодом виртуальной машины, а не инструкциями приложения. Понятно, что с подобными ошибками вам как автору прикладной программы в подавляющем большинстве случаев справиться не удастся. Ко второй группе причин возникновения асинхронных исключений относится использование устаревших и не рекомендованных для применения методов (например, Thread.stop), а также подобных им разрешённых методов (например, stopThread) из состава Java TM Virtual Machine Debug Interface ( JVMDI ) – native -интерфейса виртуальной машины, позволяющего проверять состояние работающих приложений Java и управлять ими. Указанные методы предоставляют возможность генерирования асинхронных исключений различных категорий (объявляемых и необъявляемых) в любой момент на протяжении цикла выполнения конкретного потока вычислений. Подобные механизмы рискованны и опасны просто по своей внутренней природе, поэтому их применение в большинстве случаев не поощряется.

Предложения throw s

В примере 21 в объявлении метода replaceValue ясно указано, какие объявленные исключения он способен генерировать. Язык требует предоставления подобной информации – сведения об исключениях, которые могут быть выброшены методом, важны в такой же степени, как и данные о типе возвращаемых им значений – в объявлении метода должны быть отражены и те, и другие. Объявляемые методом исключения указываются с помощью предложения throws в виде списка наименований типов исключений, разделяемых символом запятой. В списке должны присутствовать те объявляемые исключения, которые не обрабатываются в теле самого метода

Метод вправе выбрасывать исключения типов, производных от тех, которые объявлены в предложении throws – язык позволяет полиморфным образом использовать объекты производных типов в любом контексте, где предусмотрено задание объектов базового типа. Более того, метод способен генерировать исключения нескольких различных классов, производных от одного базового и при этом обнародовать в throws только один базовый класс. Следует, однако, иметь в виду, что при использовании такого подхода вы лишите программистов, которые будут обращаться к методу, ценной информации о том, какие именно исключения расширенных типов способен выбрасывать метод. С точки зрения удобства использования и возможностей развития кода предложение throws должно быть настолько полным и точным в деталях, насколько это приемлемо в конкретной ситуации.

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

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

Вызывая метод, в определении которого содержится предложение throws с перечнем объявляемых исключений, вы получаете в своё распоряжение три возможные альтернативы дальнейших действий:

· отловить исключения и обработать их;

· отловить исключения и вместо них сгенерировать исключения таких типов, которые указаны в вашем собственном предложении throws;

· объявить соответствующие исключения в собственном предложении throws и позволить им «пройти» через ваш код незамеченными.

Дата: 2019-02-19, просмотров: 255.