Chapter 5 Flow Control and Exceptions
· Unreachable statements produce a
compile-time error.
while (false)
{ x = 3; } // won’t compile
for (;false;)
{ x =3; } // won’t compile
if (false) {x
= 3; } // will compile, to provide the ability to conditionally compile
the code.
· Local variables already declared in an
enclosing block, therefore visible in a nested block cannot be re-declared
inside the nested block.
· A local variable in a block may be
re-declared in another local block, if the blocks are disjoint.
· Method parameters cannot be re-declared.
1. Loop constructs
· 3 constructs – for, while, do
· All loops are controlled by a boolean
expression.
· In while and for, the test occurs at the
top, so if the test fails at the first time, body of the loop might not be
executed at all.
· In do, test occurs at the bottom, so the
body is executed at least once.
· In for, we can declare multiple variables
in the first part of the loop separated by commas, also we can have multiple
statements in the third part separated by commas.
· In the first section of for statement, we
can have a list of declaration statements or a list of expression
statements, but not both. We cannot mix them.
· All expressions in the third section of
for statement will always execute, even if the first expression makes the loop
condition false. There is no short –circuit here.
2. Selection
Statements
· if takes a boolean arguments. Parenthesis
required. else part is optional. else if structure provides multiple selective
branching.
· switch takes an argument of byte, short,
char or int.(assignment compatible to int)
· case value should be a constant
expression that can be evaluated at compile time.
· Compiler checks each case value against
the range of the switch expression’s data type. The
following code won’t compile.
byte b;
switch (b) {
case 200: // 200 not in range of byte
default:
}
· We need to place a break statement in
each case block to prevent the execution to fall through other case blocks. But
this is not a part of switch statement and not enforced by the compiler.
· We can have multiple case statements
execute the same code. Just list them one by one.
· default case can be placed anywhere.
It’ll be executed only if
none of the case values match.
· switch can be nested. Nested case labels
are independent, don’t clash with outer case labels.
· Empty switch construct is a valid
construct. But any statement within the switch block should come under a case
label or the default case label.
3. Branching
statements
· break statement can be used with any kind
of loop or a switch statement or just a labeled block.
· continue statement can be used with only
a loop (any kind of loop).
· Loops can have labels. We can use break
and continue statements to branch out of multiple levels of nested loops using
labels.
· Names of the labels follow the same rules
as the name of the variables.(Identifiers)
· Labels can have the same name, as long as
they don’t enclose one another.
· There is no restriction against using the same identifier as a label
and as the name of a package, class, interface, method, field, parameter, or
local variable.
4. Exception
Handling
· An
exception is an event that occurs during the
execution of a program that disrupts the normal flow of instructions.
· There are 3 main advantages for
exceptions:
1. Separates error
handling code from “regular” code
2. Propagating
errors up the call stack (without tedious programming)
3. Grouping error
types and error differentiation
· An exception causes a jump to the end of
try block. If the exception occurred in a method called from a try block, the
called method is abandoned.
· If there’s a catch block for the occurred
exception or a parent class of the exception, the exception is now considered
handled.
· At least one
‘catch’ block or one ‘finally’ block must accompany a ‘try’ statement. If all 3 blocks are present, the order is important.
(try/catch/finally)
· finally and catch can come only
with try, they cannot appear on their own.
· Regardless of whether or not an exception
occurred or whether or not it was handled, if there is a finally block, it’ll be
executed always. (Even if there is a return statement in try block).
· System.exit() and error conditions are
the only exceptions where finally block is not executed.
· If there was no exception or the
exception was handled, execution continues at the statement after the
try/catch/finally blocks.
· If the exception is not handled, the
process repeats looking for next enclosing try block up the call hierarchy. If
this search reaches the top level of the hierarchy (the point at which the
thread was created), then the thread is killed and message stack trace is dumped
to System.err.
· Use throw new xxxException() to throw an
exception. If the thrown object is null, a NullPointerException will be thrown
at the handler.
· If an exception handler re-throws an
exception (throw in a catch block), same rules apply. Either you need to have a
try/catch within the catch or specify the entire method as throwing the
exception that’s being re-thrown in the catch block. Catch blocks at the same
level will not handle the exceptions thrown in a catch block – it needs its own
handlers.
· The method fillInStackTrace() in
Throwable class throws a Throwable object. It will be useful when re-throwing an
exception or error.
· The Java language requires that methods
either catch
or specify all checked exceptions that can be
thrown within the scope of that method.
· All objects of type java.lang.Exception
are checked exceptions. (Except the classes under java.lang.RuntimeException) If
any method that contains lines of code that might throw checked exceptions,
compiler checks whether you’ve handled the exceptions or you’ve declared the
methods as throwing the exceptions. Hence the name checked exceptions.
· If there’s no code in try block that may
throw exceptions specified in the catch blocks, compiler will produce an error.
(This is not the case for super-class Exception)
· Java.lang.RuntimeException and
java.lang.Error need not be handled or declared.
· An overriding method may not throw a
checked exception unless the overridden method also throws that exception or a
super-class of that exception. In other words, an overriding method may not
throw checked exceptions that are not thrown by the overridden method. If we
allow the overriding methods in sub-classes to throw more general exceptions
than the overridden method in the parent class, then the compiler has no way of
checking the exceptions the sub-class might throw. (If we declared a parent
class variable and at runtime it refers to sub-class object) This violates the
concept of checked exceptions and the sub-classes would be able to by-pass the
enforced checks done by the compiler for checked exceptions. This should not be
allowed.
Exception-->ClassNotFoundException,
ClassNotSupportedException, IllegalAccessException, InstantiationException,
IterruptedException, NoSuchMethodException, RuntimeException,
AWTException, IOException
RuntimeException-->EmptyStackException,
NoSuchElementException, ArithmeticException, ArrayStoreException,
ClassCastException, IllegalArgumentException,
IllegalMonitorStateException,
IndexOutOfBoundsException,
NegativeArraySizeException, NullPointerException, SecurityException.
IllegalArgumentException-->IllegalThreadStateException, NumberFormatException
IndexOutOfBoundsException-->ArrayIndexOutOfBoundsException,
StringIndexOutOfBoundsException
IOException-->EOFException, FileNotFoundException,
InterruptedIOException, UTFDataFormatException, MalformedURLException,
ProtocolException, SockException, UnknownHostException, UnknownServiceException.
