异常的分类与常见的异常
java.lang.Throwable 类是Java 中所有错误类或异常类的根类,两个重要子类是Error 类和Exception 类。
java.lang.Error 类是程序无法处理的错误,表示应用程序运行时出现的重大错误,这些错误都需交由系统进行处理。
java.lang.Exception 类是程序本身可以处理的异常,可分为运行时异常与编译异常。
常见的RuntimeException 有NullpointerException(空指针异常)、ClassCastException(类型转换异常)、IndexOutOfBoundsException(数组越界异常)等。
常见的编译异常有IOException(流传输异常)、SQLException(数据库操作异常)等。
下面是几种常见的异常。
- ArithmeticException(数学运算异常)。例如程序中出现了除数为0的运算,就会抛出该异常。
- NullPointerException(空指针异常)。例如当应用试图在要求使用对象的地方使用了null 时,就会抛出该异常。
- NegativeArraySizeException(数组大小为负值异常)。
- ArrayIndexOutOfBoundsException(数组下标越界异常)。
- NumberFormatException(数字格式异常)。当试图将一个String 转换为指定的数字类型,而该字符串不满足数字类型的格式要求时,就会抛出该异常。
- InputMismatchException(输入类型不匹配异常)。它由Scanner 类抛出,当读取的数据类型与期望类型不匹配时,就会抛出该异常。
异常的处理
package com.test;
public class Test {
public static void main(String args[]) {
System.out.println("** A、计算开始之前。");
try {
int result = 10 / 0; // 除法计算,有异常
System.out.println("** B、除法计算结果:" + result);
} catch (ArithmeticException e) {
//ArithmeticException代表数字运算异常
//printStackTrace得到完整的异常信息
e.printStackTrace();
} finally {
System.out.println("*** 不管是否出错,都执行!!!");
}
System.out.println("** C、计算结束之后。");
}
}
输出:
** A、计算开始之前。
java.lang.ArithmeticException: / by zero
at com.test.Test.main(Test.java:7)
*** 不管是否出错,都执行!!!
** C、计算结束之后。
此时的程序依然会发生异常,但从操作结果上来看,程序至少是正常结束了。还可以发现,在try语句中发现异常后,异常语句之后的代码将不再执行,而是跳到catch处执行处理。
catch只能捕获一种类型的异常,如果有多个异常,并且有的异常没有被捕获,程序依然会中断执行。因此需要用多个catch捕获异常。
当捕获异常类对象之后,会与指定的catch 语句中的异常类型进行匹配。如果匹配成功,则使用指定的catch 进行异常的处理;如果匹配不成功,则继续交给JVM 采用默认的方式处理,但是在此之前,会首先判断是否存在finally 代码,如果存在,则执行完finally 之后再交给JVM 进行处理,如果此时已经处理了,则继续向后执行finally 代码。
执行完finally 程序之后,如果后续还有其他程序代码,则继续向后执行。所有的异常都可以使用Exception 类处理。
使用throws抛出异常
throws 关键字是在方法声明时使用的,表示此方法中不处理异常,一旦产生异常之后将交给方法的调用处进行处理。
package com.test;
class MyMath { // 定义一个简单的数学类
public static int div(int x, int y) throws Exception { // 交给被调用处处理
System.out.println("*** A、除法计算开始。");
int temp = 0; // 保存计算结果
temp = x / y; // . 此处产生异常之后以下的代码将不再执行,操作返回给被调用处
System.out.println("*** B、除法计算结束。");
return temp;
}
}
package com.test;
public class Test {
public static void main(String args[]) {
try {
System.out.println("计算结果:" + MyMath.div(10, 0));
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出:
*** A、除法计算开始。
java.lang.ArithmeticException: / by zero
at com.test.MyMath.div(MyMath.java:7)
at com.test.Test.main(Test.java:6)
将MyMath.java修改为:
package com.test;
class MyMath { // 定义一个简单的数学类
public static int div(int x, int y) throws Exception { // 交给被调用处处理
System.out.println("*** A、除法计算开始。");
int temp = 0; // 保存计算结果
try {
temp = x / y;
} finally { // 不管是否有异常,都执行此代码
System.out.println("*** B、除法计算结束。");
}
return temp;
}
}
输出:
*** A、除法计算开始。
*** B、除法计算结束。
java.lang.ArithmeticException: / by zero
at com.test.MyMath.div(MyMath.java:8)
at com.test.Test.main(Test.java:6)
自定义异常
为了处理各种异常,可以通过继承的方式编写自定义的异常类。因为所有可处理的异常类均继承Exception 类,所以自定义异常类也必须继承这个类。
package com.test;
class DefaultException extends Exception {
public DefaultException(String msg) {
// 调用Exception 类的构造方法,存入异常信息
super(msg);
}
}
package com.test;
public class Test {
public static void main(String[] args) {
try {
// 在这里用throw 直接抛出一个DefaultException 类的实例的对象
throw new DefaultException("自定义异常!");
} catch (Exception e) {
System.out.println(e);
}
}
}
输出:
com.test.DefaultException: 自定义异常!
断言语句
断言语句的语法格式有两种:
assert 布尔表达式;
assert 布尔表达式:字符串表达式;
一般情况下,在程序中可能出现错误的地方加上断言语句,以便于调试。
package com.test;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int score;
int sum = 0;
System.out.println("请输入成绩,输入任意非数字字符结束:");
while (scanner.hasNextInt()) {
score = scanner.nextInt();// 读入成绩
// 如果输入的成绩为负数,则终止执行,显示"成绩不能为负@!"
assert score >= 0 : "成绩不能为负!";
// 如果输入的成绩大于100 分,则终止执行,显示"成绩满分为100 分!"
assert score <= 100 : "成绩满分为100 分!";
sum += score;
}
System.out.println("班级总成绩为:" + sum);
}
}
输出:
请输入成绩,输入任意非数字字符结束: