基本概念
- 异常就是"不正常"的含义,在Java语言中主要指程序执行中发生的不正常情况
- java.lang.Throwable类是Java语言中错误(Error)和异常(Exception)的超类
- 其中Error类主要用于描述Java虚拟机无法解决的严重错误,通常无法编码解决
- 如:JVM挂掉了等
- 其中Exception类主要用于描述因编程错误或偶然外在因素导致的轻微错误,通常可以编码解决
- 如:0作为除数等
- 其中Error类主要用于描述Java虚拟机无法解决的严重错误,通常无法编码解决
异常的分类
- java.lang.Exception类是所有异常的超类,主要分为以下两种:
- RuntimeException:运行时异常,也叫作非检测性异常
- IOException和其它异常:其它异常,也叫作检测性异常
- 所谓检测性异常就是指在编译阶段都能被编译器检测出来的异常,不处理就无法到运行阶段
- 注意: 当程序执行过程中发生异常但又没有手动处理时,则由Java虚拟机采用默认方式处理异常
- 默认处理方式:打印异常的名称、异常发生的原因、异常发生的位置以及终止程序
- 发生异常后,异常下面的代码不会被执行
异常的避免
- 在以后的开发中尽量使用if条件判断来避免异常的发生
- 但是过多的if条件判断会导致程序的代码加长、臃肿,可读性差
异常的捕获
语法格式
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ExceptionCatchTest {
public static void main(String[] args) {
// 创建一个FileInputStream类型的对象与d:/a.txt文件关联,打开文件
FileInputStream fis = null;
try {
System.out.println("1");
// 当程序执行过程中发生了异常后直奔catch分支进行处理
fis = new FileInputStream("d:/a.txt");
System.out.println("2");
} catch (FileNotFoundException e) {
System.out.println("3");
e.printStackTrace();
System.out.println("4");
}
// 关闭文件
try {
System.out.println("5");
fis.close();
System.out.println("6");
} /*catch (Exception e) { // Exception超类 懒人的写法
e.printStackTrace();
}*/ catch (IOException e) { // 具体异常 可读性好
System.out.println("7");
e.printStackTrace();
System.out.println("8");
} catch (NullPointerException e) { // 手动处理空指针异常
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("over!");
// 当程序执行过程中没有发生异常时的执行流程:1 2 5 6 over!
// 当程序执行过程中发生异常又没有手动处理空指针异常时的执行流程:1 3 4 5 空指针异常导致程序终止
// 当程序执行过程中发生异常并且手动处理空指针异常时的执行流程: 1 3 4 5 over!
// 手动处理异常和没有处理的区别:代码是否可以继续向下执行
}
}
finally笔试考点
public class ExceptionFinallyTest {
// 笔试考点
public static int test() {
try {
int[] arr = new int[5];
System.out.println(arr[5]);
return 0;
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
return 1;
} finally {
return 2; // 提交结束方法并返回数据
}
}
int test = test();
System.out.println("test = " + test); // 2
}
e.printStackTrace();
打印完之后想返回1结束程序,但是finally
通知它要先运行自己再结束,而finally
自己返回2,有返回值结束了程序
异常的抛出
基本概念
- 当有些异常不能处理或者不便于处理时,将该异常转移给该方法的调用者
- 当方法执行时出现异常,则底层生成一个异常类对象抛出
- 此时异常代码后续的代码就不再执行
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ExceptionThrowsTest {
public static void show() throws IOException {
FileInputStream fis = new FileInputStream("d:/a.txt");
System.out.println("我想看看你抛出异常后是否继续向下执行???");
fis.close();
}
// 不建议在main方法中抛出异常 JVM负担很重
public static void main(String[] args) /*throws IOException*/ {
try {
show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意
-
子类重写的方法不能抛出更大的异常、不能抛出平级但不相同的异常
-
可以抛出相同的异常、更小的异常以及不抛出异常
// 父类 import java.io.IOException; public class ExceptionMethod { public void show() throws IOException {} }
// 子类 import com.sun.jdi.ClassNotLoadedException; import java.io.FileNotFoundException; import java.io.IOException; public class SubExceptionMethod extends ExceptionMethod { @Override public void show() throws IOException {} // 子类重写的方法可以抛出和父类中方法一样的异常 //public void show() throws FileNotFoundException {} // 子类重写的方法可以抛出更小的异常 //public void show() {} // 子类可以不抛出异常 //public void show() throws ClassNotLoadedException {} // 不可以抛出平级但不相同的异常 //public void show() throws Exception {} // 不可以抛出更大的异常 }
经验
-
若父类中被重写的方法没有抛出异常时,则子类中重写的方法只能进行异常的捕获处理
-
若一个方法内部又以递进方式分别调用了好几个其它方法,则建议这些方法内可以使用抛出的方法处理到最后一层进行捕获方式处理
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class ExceptionThrowsTest { public static void show() throws IOException { FileInputStream fis = new FileInputStream("d:/a.txt"); System.out.println("我想看看你抛出异常后是否继续向下执行???"); fis.close(); } public static void test1() throws IOException { show(); } public static void test2() throws IOException { test1(); } public static void test3() throws IOException { // 层层调用 test2(); } public static void main(String[] args) { try { test3(); } catch (IOException e) { // 最后一层进行处理 e.printStackTrace(); } } }