Актуальность курса |
Операторы и структура кода. Исключения
Управление ходом программы
Управление потоком вычислений является фундаментальной основой всего языка программирования. В данной лекции будут рассмотрены основные языковые конструкции и способы их применения.
Синтаксис выражений весьма схож с синтаксисом языка С, что облегчает его понимание для программистов, знакомых с этим языком, и вместе с тем имеется ряд отличий, которые будут рассмотрены позднее и на которые следует обратить внимание.
Порядок выполнения программы определяется операторами. Операторы могут содержать другие операторы или выражения.
Нормальное и прерванное выполнение операторов
Последовательность выполнения операторов может быть непрерывной, а может и прерываться (при возникновении определенных условий). Выполнение оператора может быть прервано, если в потоке вычислений будут обнаружены операторы
break continue return
Тогда управление будет передано в другое место (в соответствии с правилами обработки этих операторов, которые мы рассмотрим позже).
Нормальное выполнение оператора может быть прервано также при возникновении исключительных ситуаций, которые тоже будут рассмотрены позднее. Явное возбуждение исключительной ситуации с помощью оператора throw также прерывает нормальное выполнение оператора и передает управление выполнением программы (далее просто управление) в другое место.
Прерывание нормального исполнения всегда вызывается определенной причиной. Приведем список таких причин:
- break (без указания метки );
- break (с указанием метки );
- continue (без указания метки );
- continue (с указанием метки );
- return (с возвратом значения);
- return (без возврата значения);
- throw с указанием объекта Throwable, а также все исключения, вызываемые виртуальной машиной Java.
Выражения могут завершаться нормально и преждевременно (аварийно). В данном случае термин "аварийно" вполне применим, т.к. причиной необычной последовательности выполнения выражения может быть только возникновение исключительной ситуации.
Если в операторе содержится выражение, то в случае его аварийного завершения выполнение оператора тоже будет завершено преждевременно (т.е. нормальный ход выполнения оператора будет нарушен).
В том случае, если в операторе имеется вложенный оператор и его завершение происходит ненормально, то так же ненормально завершается оператор, содержащий вложенный (в некоторых случаях это не так, что будет оговариваться особо).
Блоки и локальные переменные
Блок - это последовательность операторов, объявлений локальных классов или локальных переменных, заключенных в скобки. Область видимости локальных переменных и классов ограничена блоком, в котором они определены.
Операторы в блоке выполняются слева направо, сверху вниз. Если все операторы (выражения) в блоке выполняются нормально, то и весь блок выполняется нормально. Если какой-либо оператор (выражение) завершается ненормально, то и весь блок завершается ненормально.
Нельзя объявлять несколько локальных переменных с одинаковыми именами в пределах видимости блока. Приведенный ниже код вызовет ошибку времени компиляции.
public class Test { public Test() { } public static void main(String[] args) { Test t = new Test(); int x; lbl: { int x = 0; System.out.println("x = " + x); } } }
В то же время не следует забывать, что локальные переменные перекрывают видимость переменных-членов. Так, следующий пример отработает нормально.
public class Test { static int x = 5; public Test() { } public static void main(String[] args) { Test t = new Test(); int x = 1; System.out.println("x = " + x); } }
На консоль будет выведено x = 1.
То же самое правило применимо к параметрам методов.
public class Test { static int x; public Test() { } public static void main(String[] args) { Test t = new Test(); t.test(5); System.out.println("Member value x = " + x); } private void test(int x){ this.x = x + 5; System.out.println("Local value x = " + x); } }
В результате работы этого примера на консоль будет выведено:
Local value x = 5 Member value x = 10
На следующем примере продемонстрируем, что область видимости локальной переменной ограничена областью видимости блока, или оператора, в пределах которого данная переменная объявлена.
public class Test { static int x = 5; public Test() { } public static void main(String[] args) { Test t = new Test(); { int x = 1; System.out.println("First block x = " + x); } { int x = 2; System.out.println("Second block x =" + x); } System.out.print("For cycle x = "); for(int x =0;x<5;x++) { System.out.print(" " + x); } } }
Данный пример откомпилируется без ошибок и на консоль будет выведен следующий результат:
First block x = 1 Second block x =2 For cycle x = 0 1 2 3 4
Следует помнить, что определение локальной переменной есть исполняемый оператор. Если задана инициализация переменной, то выражение исполняется слева направо и его результат присваивается локальной переменной. Использование неинициализированных локальных переменных запрещено и вызывает ошибку компиляции.
Следующий пример кода
public class Test { static int x = 5; public Test() { } public static void main(String[] args) { Test t = new Test(); int x; int y = 5; if( y > 3) x = 1; System.out.println(x); } }
вызовет ошибку времени компиляции, т.к. возможны условия, при которых переменная x может быть не инициализирована до ее использования (несмотря на то, что в данном случае оператор if(y > 3) и следующее за ним выражение x = 1; будут выполняться всегда).