Section 2 FLOW CONTROL AND EXCEPTION HANDLING
Consider the following if-else block:
public void method1(boolean flag) //0
{
boolean bool = false;
int i = 20;
if(flag)
{
System.out.println("first if");
}
else if(flag == bool)
{
System.out.println("first else-if");
}
else if( bool )
{
System.out.println("second else if");
}
else
{
System.out.println("last else");
}
if( i = 30 ){ ... } //invalid because the expr. i = 30 returns a an int value 30
if( i == 30){ ... } //valid
if( bool = true ){ ... } //valid because the expr. bool = true returns a boolean value true
int k; //Note that k is uninitialized here.
bool = true;
if(bool)
{
k = 100; //Note that k is being initialized here. And this will always get executed as bool is true;
}
System.out.println(k); //Still this will NOT work.
}
Rules:
if(flag)
{
System.out.println("first if");
}
else
{
if(flag == bool)
{
System.out.println("first else-if");
}
else
{
if( bool )
{
System.out.println("second else if");
}
else
{
System.out.println("last else");
}
}
}
Consider the following switch block:
public void method1(integraltype i) //0
{
int k = 30;
switch(i)
{
case 100 : System.out.println(100); //1
case 150 : System.out.println(150); break; //2 invalid if i is of type bytecase 3.2 : System.out.println(i); //3 invalid
default : System.out.println(i); //position of default may be anywhere.
case 'c' : System.out.println(i); //4
case true : System.out.println(i); //5 invalid
case k : System.out.println(i); //6 invalid
}
}
Rules:
It is best to read Chapter 14 Blocks and Statements from JLS. It will look a bit intimidating for the first time, but don't give up. It'll pay off.
Consider the following method:
public void method1() throws IOException //0
{
try
{
throw new FileNotFoundException("FNE");
//System.out.println("This line Will never get executed"); //Compile time error : Unreachable code.
}
catch(NullPointerException ne)
{
throw new FileNotFoundException("FNE");
}
catch(FileNotFoundException fe)
{
//This block will NOT catch FileNotFoundException thrown by the catch block above.
//This block will ONLY catch FileNotFoundException thrown by the try block.
throw new EOFException("EOF");
}
finally
{
//This block has nothing to do with exception catching. That means if you throw an exception in try or catch block, either you have to provide an appropriate catch block or declare it in the throw clause of the method.
//It provides a way to the programmer to make sure that code in this block always executes.
//Executes even if there is a return in try/catch blocks.
//DOES NOT EXECUTE if there is System.exit() in try/catch blocks.
}
}
Concept: There are lot of rules regarding what exceptions can a method throw and they all seem to be very confusing.
But they all stem from the same concept, Plug and Play. New code should not break pre-existing code.
Consider a component
(not an AWT component but any s/w component) C that has a method m. Method m has
declared IOException in it's throws clause. Say there is another component U,
that uses C (and calls m). It needs to catch IOException, which it does and
every thing is fine. Now, instead of C, a subclass of C (say NewC) is supplied
to
U. As NewC is a subclass of C, U shouldn't feel a difference.
It's ok even if the method m of NewC, starts throwing FileNotFoundException because FileNotFoundEx
is a subclass of IOException and U is already catching it. It is somethig like this:
//in a user component U
{
...
C c = getC(); //somehow gets the component C. It may actually be NewC.
try
{
c.m(); //can potentially throw IOException. So needs a try/catch block.
}
catch(IOException ioe) //It'll work even if m() throws FileNotFoundException.
{
//handle exception
}
...
}
The above code in U will fail if m() throws some other exception like Exception or say, java.rmi.RemoteException. Now, it should be pretty clear to you that the restrictions imposed on the overriding method about exception are to promote component based architecture which allow you to treat s/w as components which you can take out and replace.
In short, an overriding method can throw any subclass of exceptions declared in the the throws clause of the superclass's method. It CANNOT throw super class exception or any new exception.
Can an overriding method have no throws clause if the overridden method does have one? Imagine such a situation and view it from the perspective shown above and you should get your answer. Hint: Think about whether the above code will fail or not if m() of NewC throws no exception.