10.1 异常情况
角标越界异常 ArrayIndexOutOfBoundsException
int[] a = new int[3];
System.out.println((a[3]));;//throw new ArrayIndexOutOfBoundsException(index);
System.out.printl("over");//前一句出现异常,程序中断,此句不执行
- 没有找到角标3,运行时发生了异常。java将出现异常的信息直接封装到对象中
- 系统自动抛出对应的异常 new ArrayIndexOutOfBoundsException(index)
- JVM进行最终处理,将问题的名称,信息,位置都显示屏幕上
运行结果
Exception in thread “main” 异常发生在名字为main的线程中 main主线程(主函数所在的线程)
java.lang.ArrayIndexOutOfBoundsException: 3 异常名称 异常原因
at Part1.test.practice.main(practice.java:8) 异常的位置(异常发生的位置)
at Part1.test.practice.main(practice.java:8) 异常的位置(调用异常发生的位置)
10.2 try…catch捕获异常
抛出异常
执行try块内代码时出现异常,系统自动生成一个异常对象,提交给Java运行时的环境
捕获异常
Java运行时的环境接收到异常对象时,开始寻找处理该异常对象的catch块,进行处理
若找不到异常对象的catch块,运行终止,程序退出
try{
//业务实现代码
.....
}catch(Exception e){//参数为一个异常类对象e
//处理异常
.......
}
每一个catch块专门用于处理该异常类及其子类的异常实例
10.3 异常类
- Throwable为所有异常类的父类
Checked异常和Runtime异常体系
Checked异常(只有JAVA提供,必须显式处理)
处理方式:
1. try…catch处理(当前方法明确知道错误)
2. 定义方法时抛出异常(当前方法不知道怎样处理)
Runtime异常(所有RuntimeException异常类及其子类)
无需显式声明抛出
- RuntimeException的常见异常子类
- ArithmeticException 数学异常 (5/0)
- FileNotFoundException 文件未找到异常
- NullPointerException 空指针异常(引用变量为null)
- IndexOutOfBoundsException 下标越界异常
- ClassCastException 类型转换异常
- NumberFormatException 字符串转换为数字异常
try{
.....
}catch(ArrayIndexOutOfBoundsException e1){
.....
}catch(RuntimeException e2){
......
}catch(Exception e3){
......
}
注意
捕获异常时,所有父类异常的catch块要放在子类异常catch块的后面
保障子类异常catch块有执行的机会
10.4 多异常捕获
- 多种异常类型之间用 | 分隔开
- 捕获多种异常类型时,异常变量默认用final修饰,不可重新赋值 2
- 捕获一种异常类型时,异常变量可重新赋值 3
try {
.........
}catch(IndexOutOfBoundsException | NumberFormatException e){
System.out.println("发生越界异常或数字格式异常!");
//e = new IndexOutOfBoundsException("test"); 2
}catch(Exception e){
System.out.println("发生其他异常!");
e = new RuntimeException("test"); //3
}
10.5 访问异常信息
通过catch块后的异常形参e来访问异常对象信息
- getMessage() 返回异常的描述字符串
- printStackTrace() 输出异常的跟踪栈信息
- getStackTrace() 返回异常的跟踪栈信息
- printStackTrace(PrintStream s) 将异常的跟踪栈信息输出到指定输出流
10.6 finally
程序在try块中打开了一些物理资源,必须显示回收。因为异常会引发程序跳转,导致不能及时回收,而finally代码块中存放的代码总是被执行
- 异常处理语法结构中,只有try块是必需的
- finally块必须在所有catch块后
- 执行finally块内容不收return影响
- 异常处理的finally块总会被执行,除非使用==System.exit(1)==退出虚拟机
try {
int[] a = new int[3];
System.out.println(a[5]);
}catch(IndexOutOfBoundsException e){
e.printStackTrace();
System.out.println();
return;
//System.exit(1)退出虚拟机,则不会再执行finally块
}catch(Exception e){
System.out.println("发生其他异常!");
}finally {
System.out.println("一定被执行");//此语句不受return影响
}
- 尽量不要再finally块中使用return,throw终止方法的语句(可能导致try块,catch块中的return,throw失效等)
finally块try块都包含终止语句时的执行步骤:
- 执行try块||catch块遇到return||throw
- 终止语句(不结束方法)寻找异常流程中的finally块
- 若找见finally块,执行包含代码
- 跳出finally块,继续执行try块||catch块中的return||throw
10.7 throws声明抛出异常
当前方法不知如何处理异常,该异常应由上一级调用者处理。
若main函数也不知如何处理异常,也可以throws声明抛出异常交由JVM处理
JVM打印异常的跟踪栈信息,终止程序执行
public static void main(String[] args)
throws IndexOutOfBoundsException{//声明越界异常
int[] a = new int[3];
System.out.println(a[5]);
}
声明多个异常之间用,隔开
throws IndexOutOfBoundsException,NullPointerException
子类声明抛出的异常类型只能是父类的子类或相同
10.8 throw抛出异常
throw抛出的是一个异常实例,每次只能抛出一个
public class throw{
public static void main(String[] args) {
try {
//调用抛出Checked类型的异常
//必须显式捕获 或 在main方法中再次抛出
throwChecked(-3);
}catch(Exception e){
System.out.println(e.getMessage());
}
//调用抛出Runtime类型的异常
//既可显式捕获,也可不做理会,交由调用者处理
throwRuntime(3);
}
public static void throwChecked(int a)throws Exception{
if(a > 0) {
throw new Exception("a的值大于0,不符合要求");
}
}
public static void throwRuntime(int a){
if(a > 0) {
throw new RuntimeException("a的值大于0,不符合要求");
}
}
}
10.9 自定义异常
//自定义异常继承自基类 Exception 或 RuntimeException
public class except extends Exception{
//无参构造函数
public practice() {
}
//通过super调用父类构造器,字符串S作为异常描述信息
public practice(String s) {
super(s);
}
}
上课异常类
public class test {
public static void main(String[] args) {
Teacher t=new Teacher("赵老师");
try {
//上课函数可能有异常
t.teach();
//若捕获到不能上课的异常,打印异常信息,下课,放学
} catch (ClassNotContinueException e) {
e.printStackTrace();
System.out.println("下课 放学!");
}
}
}
/*
老师用电脑上课
电脑会有以下几个问题
1.蓝屏 -->>重启-->>上课
2.冒烟 -->>无法上课
*/
//老师类
class Teacher{
String name;
Computer com;
public Teacher(String name) {
this.name=name;
this.com=new Computer(2);//定义电脑冒烟
}
//上课函数声明抛出不能继续上课的异常
public void teach() throws ClassNotContinueException {
try {
//电脑状态可能异常
com.start();
//捕获到蓝屏异常
} catch (BlueScreenException e) {
e.printStackTrace();
//重启
com.restart();
//捕获到冒烟异常
} catch (MaoYanException e) {
e.printStackTrace();
//异常的转换,抛出不能上课的异常
throw new ClassNotContinueException("课上不成了!");
}
//电脑正常,开始上课
System.out.println(this.name+"开始上课......");
}
}
//电脑类
class Computer{
int status=0;//0 正常 1 蓝屏 2冒烟
public Computer(int status) {
this.status=status;
}
//重启函数
public void restart() {
status=0;
System.out.println("电脑重启......");
}
//电脑状态声明抛出蓝屏,冒烟异常
public void start() throws BlueScreenException, MaoYanException{
System.out.println("电脑开机......");
if(status==1){
throw new BlueScreenException("电脑蓝屏了......");
}
if(status==2){
throw new MaoYanException("电脑主板烧了,电脑冒烟了......");
}
}
}
//蓝屏异常类
class BlueScreenException extends Exception{
public BlueScreenException(String msg) {
super(msg);
}
}
//冒烟异常类
class MaoYanException extends Exception{
public MaoYanException(String msg) {
super(msg);
}
}
//不能上课异常类
class ClassNotContinueException extends Exception{
public ClassNotContinueException(String msg) {
super(msg);
}
}