1、异常概述
在程序中,错误可能产生于程序员没有料到的各种情况,或者是超出了程序员可控范围的环境因素,如试图打开一个不存在的文件等,在Java中,,这种在程序运行时可能出现的一些错误称为异常。
2、异常的分类
Java类库中每个包都定义了异常类,所有这些类都是Throwable类的子类,Throwable 类派生出两个子类,分别是Error类和Exception类,其中,Error类及其子类用来描述Java运行系统中的内部错误以及资源耗尽的错误,这类错误比较严重,而Exception类称为非致命性类,可以通过捕捉处理使程序继续执行,Exception类又可以根据错误发生的原因分为运行时异常和非运行时异常。
2.1 系统错误-Error
Error类及其子类通常用来描述Java运行系统中的内部错误,该类定义了常规环境下不希望由程序捕获的异常,比如OutOfMemoryError,ThreadDeath等,这些错误发生时,Java一般会选择线程终止。
2.2 异常-Exception
异常是程序本身可以处理的异常,这种异常主要分为运行时异常和非运行时异常,程序应当尽量去处理这些异常。
运行时异常
运行时异常是程序运行中产生的异常,这些异常一般由程序逻辑错误引起,程序应当从逻辑角度尽量避免这类异常的发生。
常见的运行时异常如下表所示:
异常类 | 说明 |
---|---|
ClassCastException | 类型转换异常 |
NullPointerExcetion | 空指针异常 |
ArrayIndexOutOfBoundsException | 数组下标越界异常 |
ArithmeticException | 算术异常 |
ArrayStoreException | 数组中包含不兼容的值抛出的异常 |
NumberFormatException | 字符串转换为数字时抛出的异常 |
IllegalArgumentException | 非法参数异常 |
FileSystemNotFoundException | 文件系统未找到异常 |
SecurityException | 安全性异常 |
StringIndexOutOfBoundsException | 字符串索引超出范围抛出的异常 |
NegativeArraySizeException | 数组长度为负异常 |
非运行时异常
非运行时异常是RuntimeException类及其子类异常以外的异常,这类异常是必须进行处理的异常,如果不处理,程序就不能编译通过,如IOException,SQLException以及用户自定义的异常等,常见的非运行时异常有:
异常类 | 说明 |
---|---|
ClassNotFoundException | 未找到相应类异常 |
SQLExcetion | 操作数据库异常类 |
IOException | 输入/输出异常流 |
TimeoutException | 操作超时异常 |
FileNotFoundException | 文件未找到异常 |
3、捕捉处理异常
我们这里捕捉处理异常时,主要有两种处理方式,一种是使用throws关键字,一种是使用try...catch代码块。
3.1 try..catch...finally代码块
package exceptionHandler;
public class FootballTeam {
public static void main(String[] args){
try{
String str = "lili";
System.out.println(str + "年龄是:" );
int age = Integer.parseInt("20L");
System.out.println(age);
}
catch(NumberFormatException e){
e.printStackTrace();
}
catch(Exception e){
e.printStackTrace();
}
finally{
System.out.println("program over");
}
}
}
输出为
objc[85867]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk/Contents/Home/bin/java (0x10e0554c0) and /Library/Java/JavaVirtualMachines/jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10e1314e0). One of the two will be used. Which one is undefined.
java.lang.NumberFormatException: For input string: "20L"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at exceptionHandler.FootballTeam.main(FootballTeam.java:8)
lili年龄是:
program over
当try中的语句跑出异常时,程序是不会继续执行try后面的语句的,相应的,它会跳转到执行catch中的语句,而finally块中的语句时无论有没有异常都会正常执行的。
另一方面,我们可以看到上面的程序中我们定义了两个catch块,也就是说,一个try可以对应多个catch块,每个catch块捕获一种特定的异常,但这里需要注意的是,catch块的异常类顺序必须先子类后父类,否则会发生错误。
3.2 在方法中抛出异常
如果某个方法可能会发生异常,但不想在当前方法中处理这个异常,则可以使用throws、throw关键字在方法中抛出异常。
throws关键字
throws关键字通常被应用在声明方法时,用来指定方法可能抛出的异常,多个异常可以使用逗号间隔。
使用throws为方法抛出异常时,如果子类继承父类,子类重写方法抛出的异常也要和原父类方法抛出的异常相同或者是其异常的子类,除非throws异常是RuntimeException。
package exceptionHandler;
public class Shoot {
static void pop() throws NegativeArraySizeException {
int[] arr = new int[-3];
}
public static void main(String[] args){
try{
pop();
}
catch(NegativeArraySizeException e){
System.out.println("pop方法抛出的异常");
}
}
}
输出为:
objc[85890]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk/Contents/Home/bin/java (0x1028394c0) and /Library/Java/JavaVirtualMachines/jdk/Contents/Home/jre/lib/libinstrument.dylib (0x1029154e0). One of the two will be used. Which one is undefined.
pop方法抛出的异常
throw关键字
throw关键字通常用于在方法体重制造一个异常,程序在执行到throw语句时立即终止,它后面的语句都不执行。
package exceptionHandler;
public class ThrowTest {
public static void main(String[] args){
int num1 = 25;
int num2 = 0;
int result;
if(num2 == 0){
throw new ArithmeticException("这都不会,小学生都知道了,除数不能是0");
}
result = num1 / num2;
System.out.println("两个数的商为:" + result);
}
}
3.3 自定义异常
在程序中使用自定义异常类,大体可以分为以下几个步骤:
1)创建自定义异常类
2)在方法中通过throw关键字抛出异常对象
3)如果在当千抛出异常的方法中处理异常,可以使用try..catch代码块捕获并处理,否则,在方法的声明处通过throws关键字指名要抛给方法调用者的异常,继续进行下一步操作。
4)在出现异常方法的调用这种捕获并处理异常
package exceptionHandler;
class MyException extends Exception {
public MyException(String ErrorMessage){
super(ErrorMessage);
}
}
public class Tran {
static void avg(int age) throws MyException{
if(age < 0){
throw new MyException("年龄不可以使用负数");
}
else{
System.out.println("王师傅今年 " + age + " 岁了");
}
}
public static void main(String[] args){
try{
avg(-50);
}
catch(MyException e){
e.printStackTrace();
}
}
}