If a method is expected to throw any exceptions, the method declaration must declare that fact in a throws clause. If a method implementation contains a throw statement, it is possible that an exception will be thrown from within the method. In addition, if a method calls another method declared with a throws clause, there is the possibility that an exception will be thrown from within the method. If the exception is not caught inside the method with a try statement, it will be thrown out of the method to its caller. Any exception that can be thrown out of a method in this way must be listed in a throws clause in the method declaration. The classes listed in a throws clause must be Throwable or any of its subclasses; the Throwable class is the superclass of all objects that can be thrown in Java.
However, there are certain types of exceptions that do not have to be listed in a throws clause. Specifically, if the exception is an instance of Error, RuntimeException, or a subclass of one of those classes, it does not have to be listed in a throws clause. Subclasses of the Error class correspond to situations that are not easily predicted, such as the system running out of memory. Subclasses of RuntimeException correspond to many common run-time problems, such as illegal casts and array index problems. The reason that these types of exceptions are treated specially is that they can be thrown from such a large number of places that essentially every method would have to declare them.
Consider the following example:
import java.io.IOException; class throwsExample { char[] a; int position; ... // Method explicitly throws an exception int read() throws IOException { if (position >= a.length) throw new IOException(); return a[position++]; } // Method implicitly throws an exception String readUpTo(char terminator) throws IOException { StringBuffer s = new StringBuffer(); while (true) { int c = read(); // Can throw IOException if (c == -1 || c == terminator) { return s.toString(); } s.append((char)c); } return s.toString(); } // Method catches an exception internally int getLength() { String s; try { s = readUpTo(':'); } catch (IOException e) { return 0; } return s.length(); } // Method can throw a RuntimeException int getAvgLength() { int count = 0; int total = 0; int len; while (true){ len = getLength(); if (len == 0) break; count++; total += len; } return total/count; // Can throw ArithmeticException } }
The method read() can throw an IOException, so it declares that fact in its throws clause. Without that throws clause, the compiler would complain that the method must either declare IOException in its throws clause or catch it. Although the readUpTo() method does not explicitly throw any exceptions, it calls the read() method that does throw an IOException, so it declares that fact in its throws clause. Whether explicitly or implicitly thrown, the requirement to catch or declare an exception is the same. The getLength() method catches the IOException thrown by readUpTo(), so it does not have to declare the exception. The final method, getAvgLength(), can throw an ArithmeticException if count is zero. Because ArithmeticException is a subclass of RuntimeException, the fact that it can be thrown out of getAvgLength() does not need to be declared in a throws clause.
References Constructors; Errors; Methods; Runtime exceptions; The throw Statement; The try Statement; Throwable