使用throw抛出异常
当程序出现错误时,系统会自动抛出异常;除此之外,Java也允许程序自行抛出异常,自行抛出异常使用throw语句完成。
到目前为止,你只是获取了被Java运行时系统抛出的异常。然而,程序可以用throw语句抛出明确的异常。
Throw语句的通常形式如下:
throw ThrowableInstance;
这里,ThrowableInstance一定是Throwable类类型或Throwable子类类型的一个对象。简单类型,例如int或char,以及非Throwable类,例如String或Object,不能用作异常。有两种可以获得Throwable对象的方法:在catch子句中使用参数或者用new操作符创建。
下面是一个创建并抛出异常的例子程序:
class User{
private int age;
public void setAge(int age){
if(age < 0){
RuntimeException e = new RuntimeException("年龄不能为负数");
throw e;
}
this.age = age;
}
}
public class Test{
public static void main(String[] args){
User user = new User();
user.setAge(-20);
}
}
上面程序中,程序试图创建一个age=-20的对象,这在语法中是没有错误的,但是在现实生活中是不合逻辑的,因此我们在User类中进行异常处理。
该程序还阐述了怎样创建Java的标准异常对象,特别注意下面这一行:
RuntimeException e = new RuntimeException("年龄不能为负数");
throw e;
这里,new用来构造一个RuntimeException实例,括号里的语句为输出的异常信息。
我们也可以简化为一下格式:
throw new RuntimeException("年龄不能为负数");
输出结果:
Exception in thread "main" java.lang.RuntimeException: 年龄不能为负数
at xom.example.test.User.setAge(Test.java:19)
at xom.example.test.Exercise1.main(Test.java:30)
使用throws声明抛出异常
使用throws声明抛出异常的思路是:当前方法不知道应该如何处理这种类型的异常,该异常应该由上一个调用者处理,也就是说在哪里调用这个异常,就在那里处理这个异常;如果main方法也不知道如何处理这种类型的异常,也可以使用throws声明抛出异常,该异常将交给JVM处理。
一个 throws 子句列举了一个方法可能抛出的所有异常类型。这对于除Error或RuntimeException及它们子类以外类型的所有异常(也就是前面我们所讲过的checked异常)是必要的。throws声明抛出的大多是checked异常类型。一个方法可以抛出的所有其他类型的异常必须在throws子句中声明。如果不这样做,将会导致编译错误。
下面是包含一个throws子句的方法声明的通用形式:
type method-name(parameter-list) throws ExceptionClass1,ExceptionClass2{
// body of method
}
下面是一个不正确的例子。该例试图抛出一个它不能捕获的异常。因为程序没有指定一个throws子句来声明这一事实,程序将不会编译。
class ThrowsDemo {
static void throwOne() {
System.out.println("Inside throwOne.");
throw new IllegalAccessException("demo");
}
public static void main(String args[]) {
throwOne();
}
}
该程序定义了一个throwOne()方法,在这个方法里抛出一个checked异常。我们应该在这个方法后面使用throws声明throwOne( )引发IllegalAccess Exception异常:
class ThrowsDemo {
static void throwOne() throws IllegalAccessException {
System.out.println("Inside throwOne.");
throw new IllegalAccessException("demo");
}
public static void main(String args[]) {
throwOne();
}
}
但是别忘了我们前面说的,在哪里调用这个方法就在哪里处理该异常。因此,我们还要在main( )方法中定义一个try/catch 语句来捕获该异常。
class ThrowsDemo {
static void throwOne() throws IllegalAccessException {
System.out.println("Inside throwOne.");
throw new IllegalAccessException("demo");
}
public static void main(String args[]) {
try {
throwOne();
} catch (IllegalAccessException e) {
System.out.println("Caught " + e);
}
}
}
输出结果:
inside throwOne
caught java.lang.IllegalAccessException: demo
Java的内置异常
在标准包java.lang中,Java定义了若干个异常类。前面的例子曾用到其中一些。这些异常一般是标准类RuntimeException的子类。因为java.lang实际上被所有的Java程序引入,多数从RuntimeException派生的异常都自动可用。而且,它们不需要被包含在任何方法的throws列表中。Java语言中,这被叫做未经检查的异常(unchecked exceptions )。因为编译器不检查它来看一个方法是否处理或抛出了这些异常。 java.lang中定义的未经检查的异常列于表10-1。表10-2列出了由 java.lang定义的必须在方法的throws列表中包括的异常,如果这些方法能产生其中的某个异常但是不能自己处理它。这些叫做受检查的异常(checked exceptions)。Java定义了几种与不同类库相关的其他的异常类型。