You are on page 1of 17

Exception Handling

What is an exception?
A notification from the program, prompting the user to fix a big problem .

Exception handing shoudl not be used for the normal flow of control. This

is about dealing with situations that you don't expect to occur.


The first strategy?
have a kind of global error code.

In this case, we have some very well documented global variable that can be

examined whenever. If we want to signal something is wrong, we would just set


this global variable to some sort of code. When the programmer was on to
use this function/method/w.e, after it called your function (which you tagged in
the global error code), it would go and look at this special place in memory
and make sure the error code wasn't set.
o
So there'ss a value for okay, and another value for something has gone
wrong.
o
Oh, is it equal to everythingsOkay? Good!
o
ANd if not? We have to interpret the value in respect to what we have
called.
As a programmer that wanted to use the function, after we call the function,

we check error code. Based on thi function and documentation, that means this
went wrong, etc...
o
Whatever values the cError Code has would be spcific to that error.
public class Main {
public static int error_code;
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
while (s.hasNextInt()) {
do_something(s.nextInt());
if (error_code != 0) {
if (error_code == -1) {
System.out.println("Negative number error.");
} else if (error_code == -2) {
System.out.println("Even number error.");
}
error_code = 0;
}
}
s.close();
}
public static void do_something(int a) {
// Clear out error code
error_code = 0;
if (a < 0) {
// a should not be negative. Set error code and return.
error_code = -1;
} else if (a %2 == 0) {
// a should not be even. Set error code and return.

error_code = -2;
} else {
System.out.println("Successfully did something because a was odd!");
}
}
}

The drawback? It's on the progarmmer too check the code every time.
Special Return Value.
Specific return values that are interpreted as errors.

This is similar to the first strategy. There's almost no difference between

global and special; now, we just examine what is returned instead of looking at
the specific part of the code.
Usually, for functions that are meant to return a reference to some object or

reference type, we can use the value null to indicate something went
wrong.
public class Main {
public static void main(String[] args) {
String haystack = "This is my haystack";
Scanner s = new Scanner(System.in);
while (s.hasNext()) {
String needle = s.next();
int position = haystack.indexOf(needle);
if (position == -1) {
System.out.println("Error: could not find needle in haystack");
} else {
System.out.println("Found needle at " + position);
}
}
s.close();
}
}

Notice that indexOf will return the value of the substring, or return -1 if it find
nothing. So we interpret this value. We expect a value of a position to be returned to
use, but alas, not! -1 is a value that is of a specific error. \
Drawbacks?
They're inconsistent.

May not have an "out-of-domain" value to use to signal error condition.

We have limited information about the error.

We have to change every instance of it if our exception boundaries

change.
Exception Handling
Formal mechanism for detecting and dealing with exceptions.

o
Whether and how we use it is upt o us.
No matter wht language--then if there's an exception handling mechanism,

there's often two parts.


o
THere's some way of causing the exception to occur. Throwing.
And when it does occur, we have to handle the exception.

o
Catching. How we handle.

Benefits of Exception Handling?


Good software engineering--consistency, modularity, separation of concerns,

extensibility.
o
We can organize exceptions into families (modularity)
o
We can separate concerns of code that is dealing with normal condition
and code edealing with exceptional cnodition (separation of concerns).
o
Extensible--create new kinds of exceptions, extend different kinds of
exceptions. Write code that handles a group, or an overall type of
exception, even if you don't know where, specifically, it would occur.
Exceptions now wll become objects. Exceptions are objects in and of itself. It

can encapsulate into the enxception object additional information and


context about when this exception specifically occurs.
o
We can separate code into regular code (code we expect to occur) and
code that raises exception.
WHat are two kinds of exceptions?
In Java, there are checked exceptions and unchecked exceptions.

o
The stuff we see here may or may not match the mechanisms provided
in some other language...but it'll be okay
Define checked and uncheked exceptions.

o
Deal with whether or not the situation is something that could occur
and nees to be handled, vs something so exceptional/never expected,
thus when it occurs, it can be handled, but if it occurs, we don't expect it
to occur--something has gone terribly wrong.
o
Java has a way of creating exceptions that should be checked vs
exceptions that don't necessarily need to be checked every time, but if
they ocur, will kill the program. You can check and handle them, but we
don't necessarily want to force hte programmer to handle them if the
programmer is expecting the program to run without ever hitting these
exceptions.
o
Checked Exceptions:
Trying to open a file that doesn't exist.

Reaing past the end of a file.

Printer is out of ink.

o
Unchecked Exceptions: Known as Runtime Exceptions!
Logical erros that the programmer doesn't expect to happen.

If it does occur, we want to take care of it.

Out of bounds indexing of an array.

Illegal cast of object reference.


Runtime Exceptions:
To signal a runtime exception...

o
Create a RuntimeException Object, and throw that shit
public Song(String name, String artist,
double length, int rating) {
if (length < 0) {
throw new RuntimeException("Length can not be negative");

}
if (rating < 0 || rating > 5) {
throw new RuntimeException("Rating out of range.");
}

this.name = name;
this.artist = artist;
this.length = length;
this.rating = rating;
}

Throw always expects, on the right side --some kind of exception object.

Sometimes, these throw-exceptions kill the program.


What if we don't want the program to end?

We may be able to recover or deal with the problem.

We can do try-catch blocks.

o
If we are writing code that migh rresult in an exception, and we want to
specify other code to handle other certain exceptional conditions, you put
the code that might cause that exception in the try-block, and you
specify one or more catch-blocks that should handle the
exceptional conditinos as they occur.
o
Each catch-block associated with specific exception type.
o
Declares variable name, and also type name of the exception
we are trying to handle. If it executes perfectly fine, then the tryblock is executed and all the catch blocks get skipped.
If an exception does occur, then the exception was

thrown somewhere in that code. In order to throw an exception,


we create an exception object, which is thrown in the try-block, and
once that happens, each of the catch blocks examined in turn.

Start with first catch block and ask, does the


exception object HAVE AN Is_A RELATIONSHIP WITH THE
THING DECLARED IN THIS CATCH BLOCK>

IF IT DOES HAVE AN IS-A RELATIONSHIP WITH THE


CATCH BLOCK ASSOCIATED WITH IT< THEN EXECUTE THE
CODE IN THE CATCH BLOCK.

IF IT DOESNT IT GOES TO THE NEXT CATCH BLOCK,


THEN NEXT, THEN NEXT.

IF THERE IS NO MATCH BETWEEN EITHER OF THESE


THINGS, THEN WHOEVER CALLED THAT METHOD--GO
SEND THE EXCEPTION OBJECT UP THE CALL STACK. GO TO
THE METHOD THAT SENT THIS EXCEPTION.

IF THAT CODE HAPPENS TOB EI N THE TRYBLOCK,


THE WHOLE THING REPEATS.
public class Main {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
while(s.hasNextLine()) {
try {
String name = s.nextLine();
String artist = s.nextLine();

double length = s.nextDouble();


int rating = s.nextInt();
Song a_song = new Song(name, artist, length, rating);
System.out.println("Created song: " + a_song.toString());
s.nextLine();
}
catch (RuntimeException e) {
System.out.println("Something went wrong: " + e.getMessage());
s.nextLine();
}
}
s.close();
}
public Song(String name, String artist,
double length, int rating) {
if (length < 0) {
throw new RuntimeException("Length can not be negative");
}
if (rating < 0 || rating > 5) {
throw new RuntimeException("Rating out of range.");
}
this.name = name;
this.artist = artist;
this.length = length;
this.rating = rating;
}

If something is wrong, notice how the catch thing skips o next line and
tries again.
Extending RuntimeException.
A little more descriptive, or specific exceptions.

If our constructor or methods is given an illegal argument, we need to give an

illegal argument exception.


o
RuntimeException has an Illegal Argument; much more specific!. Give
your own exception and behavior that might be useful.
Extending RuntimeException
One of the benefits of having a formal exceptionhandling mechanism--it can be
extended.
extends is the same as RuntimeException, and it will be a RunTime Exception--but it
will be a RuntimeException with just a little bit more.
public class NegativeSongLengthException extends RuntimeException {

private double illegal_length;


public NegativeSongLengthException(double length) {
super("Length cannot be negative.");
illegal_length = length;
}
public double getIllegalLength() {
return illegal_length;
}
@Override
public String getMessage() {
return super.getMessage() + " (" + illegal_length + ")";
}
}
@SuppressWarnings("serial")
public class RatingOutOfRangeException extends RuntimeException {
private int out_of_range_rating;
public RatingOutOfRangeException(int rating) {
super("Rating out of range");
out_of_range_rating = rating;
}
public int getOutOfRangeRating() {
return out_of_range_rating;
}
@Override
public String getMessage() {
return super.getMessage() + " (" + out_of_range_rating + ")";
}

}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
while(s.hasNextLine()) {
try {
String name = s.nextLine();
String artist = s.nextLine();
double length = s.nextDouble();
int rating = s.nextInt();
Song a_song = new Song(name, artist, length, rating);
System.out.println("Created song: " + a_song.toString());
s.nextLine();
} catch (RuntimeException e) {
System.out.println("Something went wrong: " + e.getMessage());
s.nextLine();
}
}
s.close();
}

Notice that the catch-block of Song will catch either out of range or negative-length
exceptions.

try {
String name = s.nextLine();
String artist = s.nextLine();
double length = s.nextDouble();
int rating = s.nextInt();
Song a_song = new Song(name, artist, length, rating);
System.out.println("Created song: " + a_song.toString());
s.nextLine();
}
catch (RatingOutOfRangeException e) {
System.out.println("Rating out of range:" + e.getOutOfRangeRating());
s.nextLine();
}
catch (NegativeSongLengthException e) {
System.out.println("Length is negative: " + e.getIllegalLength());
s.nextLine();
}
catch (RuntimeException e) {
System.out.println("Unknown exception: " + e.getMessage());
s.nextLine();
}
}
s.close();
}

Notice that, in this new Main method, only the first error that matches is going
to be run.
Say we entered a song artist, then we write the length as -1 and the rating is 10 We
think that NegativeSongLength will be caught.
And this is what happens. because the length is the first error that is
determined.
But if we have song, artist, 1, 10, then rating is out of range.
Illegal Argument Exception is a RunTime Exception, so it will be caught by the final
catch-block.
When can we suppress an error? How?
You can mark a class as being serializable. This means that a class knows

how to turn itself into a sequence of bites that can be read on a disk.
You can serialize an object on a disk and restore it later.
This has to do with version control and making sure that classses being used

in a project.
If you claim a class is serializable, the objects of your class have to provide a unique
ID.
Sometimes, we need code to run no matter what happens. This is where we can use
finally block.

To free up system resource, we can close a file or a network connection. If we


end a program, then we can end it completely regardless if an exception
happens. If, in the middle of a try block, and you return from the method, the
finally block WILL EXECTURE STILL.

public static void main(String[] args) {


Scanner s = new Scanner(System.in);
while(s.hasNextLine()) {
try {
String name = s.nextLine();
String artist = s.nextLine();
double length = s.nextDouble();
int rating = s.nextInt();
Song a_song = new Song(name, artist, length, rating);
System.out.println("Created song: " + a_song.toString());
} catch (NegativeSongLengthException e) {
System.out.println("Length is negative: " + e.getIllegalLength());
} catch (RatingOutOfRangeException e) {
System.out.println("Rating out of range:" + e.getOutOfRangeRating());
} catch (RuntimeException e) {
System.out.println("Unknown exception: " + e.getMessage());
} finally {
s.nextLine();
}
}
s.close();
}

The finally block isn't necessarily for these kinds of situations.


Finally blocks are for cleaning up things that you shouldn't abandon.
The THROWABLE CLASS HIERARCHY.

Anything that has an is-a relationship with Throwable can be used with
the Throw keyword. That's why we can't throw a new ArrayList, or anything like
that.
Throwable's main subclasses are error and exception.
We mostly ignore Error. and Its subclasses are not very important or

encountered. The idea is that anything that is an error is something that is


external to the program and shouldn't be caught at all. It's not
something that your program can make right.
o
Exceptions to this--some printer software that will say I'm Out Of
Ink! The program can't fix that, but we can fix the ink.
o
However, we can throw the error which says "I'm Out Of Ink."
Exception is another subclass, with RuntimeException.

o
Now, we can decide what is checked or unchecked exceptions.
What are checked and unchecked exceptions?
Unchecked exceptions include Error, RuntimeException, and their

subclasses. These are the ones which are deemed unchecked. If there's no
difference between the mechanics of checked and unchecked, what does tha
tmean?
All other subclasses of Exception are "checked".

What does it mean to be checked?


A checked exception is one that is subject to follow the catch-or
specify rule.
o
If there is a chance that a checked exception might be thrown, IT HAS
TO BE IN A TRY BLOCK, AND THERE HAS TO BE A CATCH BLOCK
WHICH HANDLES THAT EXCEPTION.
o
OR....THE METHOD THAT HAS THIS CODEMUST SPECIFY IN ITS
DECLARATION ALL OF THE CHECKED EXCEPTIONS THAT COULD BE
A RESULT OF THIS METHOD.
o
THE CATCH OR SPECIFY REQUIREMENT IS APPLIED TO
ANYTHING WHICH CALLS THE METHOD.
o
It must be able to tell any other method that causes it, and declare
that all of the checked exceptions that might be ar esult of calling this
method.
o
Any code which calls the method which lists those exceptions that
might take place, and they ahve to either catch ors pecify it.
Why force the method to either catch or specify checked exceptions?

o
It forces the user of the method t explicityl acknowledge--forces strong
software engineering practices by makin it so that the programmer
can't just ignore the issue. They have to deal with it one way or
another.
o
Unchecked exceptions might arise, but still might be able to
handle checked and unchecked exceptions. THERE IS NO
DECLARATION THAT A METHOD MIGHT CAUSE THEM. Unchecked
exceptions are just RuntimeExceptions. The idea behind it is that
unchecked exceptions are ones that don't have to be explicityly
acknowledged or dealt with one way or another. They might occur
and cause your program to crash if you don't have code to catch

it, but that's on us...a checked exception is something that forces


the programmer to indicate, one way or the other, that this guy
has to handle it.
SHOULD WE TREAT UNCHECKED METHODS LIKE CHECKED METHODS? IS
THIS A GOOD PRACTICE?
public Song(String name, String artist,
double length, int rating) throws NegativeSongLengthException, RatingOutOfRangeException {
if (length < 0) {
throw new NegativeSongLengthException(length);
}
if (rating < 0 || rating > 5) {
throw new RatingOutOfRangeException(rating);
}
if (name.equals("") || artist.equals("")) {
throw new IllegalArgumentException("Name or Artist is empty string");
}
this.name = name;
this.artist = artist;
this.length = length;
this.rating = rating;
}

Here is how we fulfill the catch-or-specify rule.


Why did we specify and not catch?
THe song constructor doesn't know how its being used, why these things

occur. It is a part of a larger program that may or may not have methods to
deal with out of range exceptions, negative song lengths. We don't really know
what's supposed to happen when these things end up out of range or negativelenght.
If we don't know what needs to happen, we are better of fspecifying.

Recall that catch blocks are evaluated for having an is-a relationship with the type
of exceptiond eclared in the catch-block. One thing this implies is that you
have to order your catch blocks from SPECIFIC TO GENERAL.
So if we put the RuntimeException block before the OutOfRangeException, then the
RuntimeException block.
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
while(s.hasNextLine()) {
try {
String name = s.nextLine();
String artist = s.nextLine();
double length = s.nextDouble();
int rating = s.nextInt();
Song a_song = new Song(name, artist, length, rating);

System.out.println("Created song: " + a_song.toString());


}
catch (NegativeSongLengthException e) {
System.out.println("Length is negative: " + e.getIllegalLength());
}
catch (RatingOutOfRangeException e) {
System.out.println("Rating out of range:" + e.getOutOfRangeRating());
} catch (RuntimeException e) {
System.out.println("Unknown exception: " + e.getMessage());
}
finally {
s.nextLine();
}
}
s.close();
}
}

What happens if we dno't use NEgativeSongLength Exception?


Well, the declaration of the constructor indicated a list of all of the exceptions

that could occur.


Now, the compiler has the information it needs to do the analysis of your

code to say, for every single ofe of those checked exceptions, it will still find it
somehow.
What aboue the addition of catch (Exception e) {}?
You do have to put in a catch block that will run, which has an is-a relationwith each
checked exception.
GENERAL PRINCIPLE: BE SPECIFIC.
Princilpes for using exceptions--one, if we have an exception that describes a

situation well, just use it.


If we lready have an existing exception type which applies to the situation

reasonably well, then use it.


If you don't have an existing exception type that runs particularly well,
create your own.
Do we want this to be checked or unchecked exception?

o
If we want it to be unchecked, subclass RuntimeException.
o
If we want it to be checked, subclass Exception.
HOW PROMINENT DO WE WANT THE EXCEPTION TO BE IN OUR

PROGRAM'S TExT?
o
Do you expect other programmers to use the program that you write?
Do they expect that you will account for these errors to be caught? Then
you need to be catching exceptions.
o
Over the years, however, programmers hate the catch/specify
rule...It encourages people to make this code try to block all the
catches from exception...so most people use unchecked
exception.
o
We can try to avoid using checked exceptions, omost of the time. It
works against good practice, etc.

C# treats everything as a RuntimeException. When we are deciding on


what kind of exception, there's good reasons to use a checked exception
that needs to be dealt with.
If your code is able to catch an exception, or detect an exceptional
condition due to something that happens down the line of the
program, and can turn that exception into something more specific to
your program...
o

public class Playlist {


private Song[] playlist_songs;
private Playlist(Song[] songs) {
playlist_songs = songs;
}
public static Playlist readFromFile(String filename)
throws PlaylistFormatException {
ArrayList<Song> songs = new ArrayList<Song>();
Scanner scanner = null;
try {
scanner = new Scanner(new File(filename));
}
catch (FileNotFoundException e) {
System.out.println("File " + filename + " doesn't exist");
System.exit(-1);
}
try {
while (scanner.hasNext()) {
String song_name = scanner.nextLine();
String artist_name = scanner.nextLine();
double length = scanner.nextDouble();
int rating = scanner.nextInt();
// Need this next call to skip rest of line
scanner.nextLine();
Song next_song = new Song(song_name, artist_name, length,
rating);
songs.add(next_song);
}
} catch (NoSuchElementException e) {
throw new PlaylistFormatException("Error in playlist after "
+ songs.size() + " songs");
} finally {
scanner.close();
}
return new Playlist(songs.toArray(new Song[0]));
}
public void print() {
for (Song s : playlist_songs) {
System.out.println(s.toString());
}
}
}

Scanner can sraise exceptions when it is asked to parse something that it does not
know.
So the specific exception scanner raises-- NoSuchElementException. This might
be something that our program can recover from.
But if we don't have a try block and don't catch the NoSuchElementException...
Scanner stays open even though we try to close it.

The actual exception that's thrown, NoSuchElementException, doesn't make

as much sense to somebody who is using code "Read From File".


It would be better if the code that was using this method had a more specific
exception instead of just NoSuchElementException.
We can just create our own exception type that is more specific to our code, etc...
public class PlaylistFormatException extends Exception {
public PlaylistFormatException(String message) {
super(message);
}
}

Anyone that uses this method needs to acknowledge that hey, if this file is not the
right format, you need to either deal with it or indicate that this has to be fixed.
In the actual method, we catch the exception that is raised by the scanner
and, what we do with it, is create a new exception and throw that one
instead!
try {
Playlist p = Playlist.readFromFile(playlist_file);
p.print();
} catch (PlaylistFormatException e) {
System.out.println(e.getMessage());
System.exit(-1);
}

Now, we can throw a more specific exception to what is actually


happening. We can even turn unchecked to checked, checked to
unchecked.
In our declaration, we say thta this could occur.

And in our program, in order to use readFromFile, we find a way to catch this

FormatException.
Say we asked for a double, but find ther eis no double here.

Then the code reading ht eplaylist would turn this into a more specific

exception.
Our program had to acknowledge that these exceptions that oculd occur...but if it
didn't, then the program will say, UNHANDLED EXCEPTION TYPE.
If you really want this unchecked exception to go all the way to main, the
main method can also specify these things.
public static void main(String[] args) throws PlaylistFormatException {
if (args.length != 1) {

System.out.println("Must specify playlist file as argument to program.");


System.exit(-1);
}
String playlist_file = args[0];
try {
Playlist p = Playlist.readFromFile(playlist_file);
p.print();
} catch (PlaylistFormatException e) {
System.out.println(e.getMessage());
System.exit(-1);
}
}

This catch-specify thing goes all the way to the top.


A few different things going ion here.
Use an exception specific to situation

If you canc atch low-level exceptions and turn them into higher-level

exceptions--if we can turn it into something that is more descriptive of what ha


shappened--do it.
General Principle: CATCH LATE.
YOu don't want to catch until you know that the action you're going to

take is the action that shouldalways happen in the situation.


Generally, you want exceptions to rise to a level where the system has
enough uncrstanding for the context to deal with the error effectively and
correctly.
IF YOU CATCH TOO EARLY!?!?!?
These exceptions don't rise to the area of the program that can deal

with these exceptions.


Pass the buck unless response to this exception UDNER ALL OR

NEARLY ALL CIRCUMSTANCES IS WELL-UNDERSTOOD.


o
You can...in theory, catch the error easily, at the beginning, and
generically, then it;s no good. But if you do it too early, you
o
...
public static Playlist readFromFile(String filename)
throws PlaylistFormatException {
ArrayList<Song> songs = new ArrayList<Song>();
Scanner scanner = null;
try {
scanner = new Scanner(new File(filename));
}

Say that we open scanner = new Scanner(new File (filename((; before the try-block.
Well, the program will complain. Just catching filenotFound and closing the program
is not always the right thing to do. We should change this so that instead of
catching it...
Since we don't know what the program is going to do, we should do specify.

We can add it to the list of exceptions that our program can throw.

public static Playlist readFromFile(String filename)


throws PlaylistFormatException, FileNotFoundException {
ArrayList<Song> songs = new ArrayList<Song>();
Scanner scanner = new Scanner(new File(filename));
try {
while (scanner.hasNext()) {
String song_name = scanner.nextLine();
String artist_name = scanner.nextLine();
double length = scanner.nextDouble();
int rating = scanner.nextInt();
// Need this next call to skip rest of line
scanner.nextLine();
Song next_song = new Song(song_name, artist_name, length,
rating);
songs.add(next_song);
}
} catch (NoSuchElementException e) {
throw new PlaylistFormatException("Error in playlist after "
+ songs.size() + " songs");
} finally {
scanner.close();
}
return new Playlist(songs.toArray(new Song[0]));
}

A different program has a small loop that asks for the playlist to be read. If the file is
not found, it gives us a message and tells us to try again. If we can't find the file,
then there's nothing to do; the program just fails.
But a different program will have a different response ot a file being unfound.
We want to catch as late as we can. We want that exception to bubble up to give
us a high enough view for the system or the program as a whole.

General Principle: THROW EARLY.


You want to...if you know that a method expects certain values to not be

null and certain values to not be in range, if we know the method will
complain if the thing given to it was null or out of range, just....let it happen.
o
But intstead of letting the illegal situation or problem keep going into a
deeper level.
The code we need to write to catch an exception early may be just as hard as

the code that we are writing to call.

At the same time, by throwing early, we cathct he problem earlier. So this is good
for nullPointerReferences.
FOR SUBPICTURE::
We have SubPicture class that takes in a Picture reference and represents the

subArea of it. We encapsulate a reference from that source picture and get
some information as that subarea.
To construct SUbPicture, we don' teven have to test that the Picture object is

null. Null is a valid value for reference types. We can save that as our source
picture in the geometry.
But...later on, when we call getPixel, when we try to use that reference to the

source picture, because it's null, it will cause NullPointerException...so where


was the error?
The error was when we called the constructor for the Picture. We didn't

catch it then, though--wwe didn't detect the situation at that point.


We allowed that illegal situation to result in a SubPicture object that
won't work, and we waited until some other code tried to use that
early...
BY NOT THROWING EARLY, BY NOT DETECTING THINGS EARLY, then if

somebody does it, they will get to a problem...


But...you did make it very hard for the person using your code.

Later on, in some other pat of the code that's very far away, then we

have to puzzle back...


o
So if we throw early, we can focus the attention more on where
the error actually occurred.
Sometimes...we can't do this, because it means repeating soooo much
code in a lot of areas of our wrok. But for the most part, the general
principle is to throw early.
ANYTHING DONE IN THE TRY-BLOCK IS ONLY FOR THE TRY-BLOCK.
REmember that the scope of the variable is limited to the surrounding block!

As soon as our try-block is done, that variable will no longer be in scope.


Sibling catch-blocks cna reuse the same variable name fo the declared error object.
When we did catch-blocks, n the declaration of the catch-block, we had a

type and then e. The next block can resuse e and reuse the same variable
name in the declaration.
A catch-block associated with an exception class cannot precede a catch

block associated with a subclass.


We can nest try-catch-finally blocks.
Inside a catch-block, we can do another try block with its own specific catch

blocks.
This catch-or-specify requirement not only affects how we declare the methd--but it
also affects how we declare interfaces.

If the implementaiton of the interface matches the implementaiton of the method,


and some checked exceptions need to be declared, this has to be in the signature
of the interface.
FINALLY ALWAYS RUNS!!!

You might also like