Java uses both checked and unchecked exceptions. The programmer must deal with checked exceptions, but is allowed to ignore unchecked exceptions.
Unchecked exceptions include Error
,
RuntimeException
and all of their subclasses. All other
exceptions are checked exceptions.
An exception handler in Java has a try-catch
structure:
Integer i = null; try { i = Integer.parseInt(someString); } catch (NumberFormatException ex) { output.println("The entered string was not an integer"); }
It is common to have a block of code that contains many
method invocations that could throw exceptions. Also, many
methods can throw more than one kind of exception. In such
circumstances, you can use more than one catch
block.
You need to remember three things when using multiple
catch
blocks:
catch
blocks are scanned in the order
that they appear, and the first block that can handle the thrown
exception is chosen as the handler.try
block.
Doing so leads to a compiler error.catch
blocks must be reachable; if not,
then the compiler will issue an error.catch
blocks are scanned in orderLab 11.1 (page 422) of the textbook introduces client-server (network) programming. Network programming involves IO that occurs over a network connection. The IO occurs via a socket. Creating a socket in Java requires that the programmer deal with two checked exceptions:
public Socket(String host, int port)
throws UnknownHostException, IOException
Creates a stream socket and connects it to the specified port number
on the named host.
Because UnknownHostException
is substitutable
for IOException
, you could use one catch
block that catches IOException
; however, you might
want to deal with the exceptions in different ways. Catching
both UnknownHostException
and IOException
gives you this opportunity.
// complete client and server programs at the end of slides Socket socket = null; boolean done = false; while (socket == null && !done) { try { output.println(); output.print("Server IP (\"done\" to quit): "); String serverName = input.next().trim(); if (serverName.equalsIgnoreCase("done")) { done = true; } else { output.print("Port number: "); Integer port = Integer.parseInt(input.next().trim()); socket = new Socket(serverName, port); output.println("Connected to server"); // more code here... } } catch (UnknownHostException ex) { output.println(ex); output.println("Check the hostname"); } catch (IOException ex) { output.println(ex); output.println("Check the hostname and port number"); output.println("Make sure the server is running"); } catch (NumberFormatException ex) { output.println("Please enter an integer port number."); } }
Java requires that a method must indicate that it throws a checked exception in the method header:
public Socket(String host, int port)
throws UnknownHostException, IOException
As a programmer, you must deal with all checked exceptions, but you cannot include a handler for an checked exception that is not thrown:
try
{
socket = new Socket(someHostName, somePortNumber);
}
catch (UnknownHostException ex)
{
// ...
}
catch (IOException ex)
{
// ...
}
// compiler error
catch (SQLException ex)
{ }
Note that Java does not require unchecked exceptions to appear
in the method header so there is no way for the compiler to
verify if a method throws an unchecked exception; thus, you can
catch whatever unchecked exception you want, even if the code
in the try
block can never cause such an exception
to occur.
catch
blocks must be reachableSubstitutability affects the order in which you must place the
catch
blocks. If one type of exception you want to
catch is a subclass of another type of exception you want
to catch, then the subclass exception handler must appear before
the superclass exception handler.
try
{
socket = new Socket(someHostName, somePortNumber);
}
// compiler error;
// UnknownHostException handler is unreachable
catch (IOException ex)
{
// ...
}
catch (UnknownHostException ex)
{
// ...
}
The problem in the example above is that
UnknownHostException
is a subclass of
IOException
. If an UnknownHostException
is thrown, it will always be caught by the IOException
(because UnknownHostException
is
substitutable for IOException
).
We say that the UnknownHostException
handler
is unreachable, and the compiler will issue a compilation error.
An unchecked exception is an exception that the programmer
does not have to catch; they are generally caused by programming errors
or events outside the control of the program. Unchecked exceptions
may appear under the "Throws" section of a method's API, but it does
not appear in the method header. Unchecked exception objects are instances
of Error
, RuntimeException
, or one of their
subclasses.
An checked exception is an exception that the programmer
must catch*; they are events that any well-written program
should anticipate and deal with. Checked exceptions
appear under the "Throws" section of a method's API, and must
appear in the method header. Checked exception objects are instances
Exception
, or one of its
subclasses (other than RuntimeException
).
You are supposed to solve eCheck11A without using any
control statements (like if
or switch
).
The goal is to interpret a user-supplied comma delimited string as the time of day, and compute the number of minutes since midnight. There are also 4 possible error conditions that you have to check for.
Input | Minutes since midnight | Error message |
---|---|---|
12:10:am | 10 | |
1:25:PM | 805 | |
15:00:am | Values out of range! | |
3:30pm | Missing colon! | |
12:fifteen:am | Non-numeric data! | |
7:59:TM | Invalid AM/PM indicator! |
The 4 error conditions are detected by catching exceptions.
Missing colon:
Use a StringTokenizer
with
":"
as the delimiter. Ask the tokenizer for 3 tokens
(hours, minutes, am/pm) and catch NoSuchElementException
.
Non-numeric data:
Catch NumberFormatException
Invalid AM/PM indicator:
Use Step 7 in the question and
catch IndexOutOfBoundsException
.
Values out of range:
?
Finish reading Chapter 11 if you haven't done so already.
From Lab 11.1 of the textbook.
import java.net.*; import java.io.*; import java.util.*; public class Client { public static void main(String[] args) { PrintStream output = System.out; Scanner input = new Scanner(System.in); Socket socket = null; boolean done = false; while (socket == null && !done) { try { output.println(); output.print("Server IP (\"done\" to quit): "); String serverName = input.next().trim(); if (serverName.equalsIgnoreCase("done")) { done = true; } else { output.print("Port number: "); Integer port = Integer.parseInt(input.next().trim()); socket = new Socket(serverName, port); output.println("Connected to server"); output.println(); PrintStream out = new PrintStream(socket.getOutputStream()); InputStreamReader r = new InputStreamReader(socket.getInputStream()); BufferedReader in = new BufferedReader(r); output.println("Enter an integer [ENTER=sentinel]"); output.print("> "); String request = input.nextLine().trim(); request = input.nextLine().trim(); for(; request.length() != 0; request = input.nextLine()) { out.println(request); output.println(in.readLine()); output.print("> "); } socket.close(); } } catch (UnknownHostException ex) { output.println(ex); output.println("Check the hostname"); } catch (IOException ex) { output.println(ex); output.println("Check the hostname and port number"); output.println("Make sure the server is running"); } catch (NumberFormatException ex) { output.println("Please enter an integer port number."); } catch (IndexOutOfBoundsException ex) { } } } }
From Lab 11.1 of the textbook.
import java.net.*; import java.io.*; import java.util.*; public class Server { public static void main(String[] args) { PrintStream output = System.out; final int PORT = 4413; try { ServerSocket serverSocket = new ServerSocket(PORT); Socket socket = serverSocket.accept(); output.println(); output.println("Accepted connection from " + socket.getInetAddress()); output.println("Waiting for an integer"); PrintStream out = new PrintStream(socket.getOutputStream(), true); InputStreamReader r = new InputStreamReader(socket.getInputStream()); BufferedReader in = new BufferedReader(r); String request = in.readLine(); for(; request != null; request = in.readLine()) { int i = 0; try { i = Integer.parseInt(request); } catch (NumberFormatException ex) {} out.println(Math.sqrt(i)); } socket.close(); serverSocket.close(); } catch (IOException ex) { output.println(ex); } } }