什么是异常
在程序运行时打断正常程序流程的任何不正常的情况称为错误或异常。异常包括用户造成的异常和
系统造成的异常。
例如:网络连接中断、操作符越界、加载的类找不到
异常产生的原因和分类
1. 异常产生的原因
在Java中异常产生,主要是有三种原因:
-
编写程序代码中的错误产生的异常,比如数组越界、空指针异常等,这种异常叫做未检查的异常,一般需要在类中处理这些异常
-
Java内部错误发生的异常,Java虚拟机产生异常
-
通过throw(抛出异常)语句手动生成的异常,这种异常叫做检查的异常,一般是用来给方法调用者一些必要的信息
2.异常分类
Throwable:是异常类根类,其派生出两个重要的子类, Error 和 Exception
- Exception类 表示可预料异常,可以处理或恢复;
- Error类 表示不可预料异常,不能处理或恢复。
异常处理方法
1.捕获并处理异常
try-catch-finally语句
try-catch-finally语句捕获程序中产生的异常,然后针对不同的情况采取不同的处理程序进行处理。
try-catch-finally语句基本格式
java
try{
Java statements //一条或多条可能抛出异常的Java语句
}catch(Exception e){
Java statements //Exception类型的异常(所有可处理的异常)执行的代码
}finally{
//无论是否存在异常,始终被执行的代码
}
执行情况:
- 情况1:try块中代码没有出现异常,不执行catch块代码,执行catch块后面的代码;
- 情况2:try块中代码出现异常,catch中异常类型匹配(相同或者父类),Java会生成相应的异常对象,Java系统寻找匹配的catch块。执行catch块后面的代码,try块中代码不会执行;
- 情况3:try块中代码出现异常,catch中异常类型不匹配,不执行catch块代码,只执行finally{}中的代码,不执行catch块后其他的代码。
- 情况4:一段代码可能会引发多种类型的异常,当引发异常时,会按顺序来查看每个 catch 的异常类型,并只执行第一个与异常类型匹配的 catch 中的异常处理代码,其他的 catch 中的异常处理代码将不会执行
注:catch块中如何处理异常:其中一种方式------自定义内容输出
例1:情况1
Java
public class ExceptionDemo01 {
public static void main(String[] args) {
int a =10;
int b = 2;
try {
int c = a / b;
System.out.println(c);
} catch (ArithmeticException e) { //捕获ArithmeticException异常,对于初学者来说,建议直接写Exception,因为它可以捕获所有异常
System.out.println("除数不能为0");
}finally {
System.out.println("程序结束");
}
}
}
Java
//运行结果:
5
程序结束
例2:情况2
java
public class ExceptionDemo01 {
public static void main(String[] args) {
int a =10;
int b = 0;
try {
int c = a / b; //除数为0,出现异常
System.out.println(c);
} catch (ArithmeticException e) { //catch中异常类型匹配,执行catch块后面的代码
System.out.println("除数不能为0");
}finally {
System.out.println("程序结束");
}
}
}
Java
//运行结果
除数不能为0
程序结束
例3:情况3
Java
import java.util.InputMismatchException;
public class ExceptionDemo01 {
public static void main(String[] args) {
int a =10;
int b = 0;
try {
int c = a / b; //除数为0,出现异常
System.out.println(c);
} catch (InputMismatchException e) { //catch中异常类型不匹配,不执行catch块代码
System.out.println("除数不能为0");
}finally { //执行
System.out.println("程序结束");
}
System.out.println("程序结束0000"); //不执行
}
}
Java
//运行结果
程序结束
2.将方法中的异常抛出
两种抛出异常方式:throw和throes
throw用于在代码中抛出异常
格式如下:
java
throw new 异常类型;
throws用于在方法中抛出异常
格式如下:
Java
方法名() throws 异常类型{
//方法体
}
例:
Java
//提取一个方法:两个数相除
public static void devide() throws Exception { //throws
int a =10;
int b = 0;
if(b == 0) { //如果b等于0,抛出异常
//人为制造异常对象
throw new Exception("除数不能为0"); //throw
}else {
System.out.println("两个数相除:"+a/b);
}
}
throw和throws的区别:
- 位置不同:throw在方法内部;throws在方法的声明处
- 内容不同:throw + 异常对象;throws + 异常类型
- 作用不同:throw:异常出现的源头,制造异常;throws在方法声明处,告诉方法调用者,这个方法可能会出现我声明的这些异常。然后调用者对这个异常进行处理:要么自己处理要么继续向外抛出异常。
异常的传播
当某个方法抛出异常时,如果当前方法没有捕获异常,异常就会抛到上层调用方法,知道遇到某个try...catch被捕获为止。
Java
public class Main{
try{
process1();
}catch(Exception e){
e.printStackTrace();
}
}
static void process1(){
process2();
}
static void process2(){
lnteger.parselnt("abc"); //抛出异常
}
printStackTrace()方法
可以打印出方法的调用栈,对于调试错误非常有用(每层方法调用均给出了源代码的行号,可以直接定位产生异常的代码位置
Java异常结构图
Exception的分类
RuntimeException 运行时异常(非检查型异常)
编译器不强制处理异常。常见运行时异常(非检查型异常)
NullpointerException:空指针异常
ClassCastException:类型强制转换异常
IllegalArgumentException:传递非法参数异常
IndexOutOfBoundsException:下标越界异常
NumberFormatException:数字格式异常
ArrayIndexOutOfBoundsException: 数组越界异常。
ArrayStoreException:数组类型不一致异常
ArithmeticException:算术异常(除0异常)
BufferOverflowException:缓冲区溢出异常
CheckedException 非运行时异常(检查型异常)
编译器强制处理异常,否则显示编译错误。常见非运行时异常 (检查型异常):
ClassNotFoundException:找不到指定 class 异常
IOException:IO 操作异常
FileNotFoundException:文件不存在异常
SQLException:SQL语句异常
InterruptedException:中断异常
异常处理机制的特点
- 通过异常传播可以将异常传递到合适的位置再处理,使得Java语言的异常处理更加灵活;
- 可以在源代码级别将正在执行的逻辑代码和异常处理的代码相分离,更加便于代码阅读和维护;
- 过度使用异常处理将降低程序的执行效率,增加语法的复杂度。