JAVA的异常解析

JAVA的异常解析

java(3)-深入理解java异常处理机制

【Java】全面解析异常(异常的分类、处理、抛出和捕获等)

异常结构图

在这里插入图片描述

Throwable

在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)。Throwable 指定代码中可用异常传播机制通过 Java 应用程序传输的任何问题的共性。

Error

  • Error指的是Java虚拟机无法解决的严重问题,大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM出现的问题。
  • AWTError,当发生严重的抽象窗口工具包错误时抛出
  • VirtualMachineError,抛出以指示Java虚拟机损坏或已耗尽继续运行所需的资源。
    • 其子类OutOfMemoryError,内存溢出,当Java虚拟机由于内存不足而无法分配对象时抛出,并且垃圾收集器无法提供更多内存。
    • 子类StackOverflowError,栈溢出,当由于应用程序递归太深而发生堆栈溢出时抛出。

Exception

  • Exception是指异常,定义上分为运行时异常RuntimeException(不可查异常unchecked Exceptions)和编译时异常(也称可检查异常checked Exceptions)
    • 运行时异常的特点是Java编译器不会检查它,是由程序逻辑错误引起的。当程序中可能出现这类异常,即使没有用try-catch语句捕获它或者没有用throws子句声明抛出它,也会编译通过。
      • IndexOutOfBoundsException,越界异常,抛出以指示某种排序(如数组、字符串或向量)的索引超出范围。
      • ArithmeticException,算术异常,发生异常算术条件时抛出。例如,整数“除零”抛出该类的一个实例。
      • NullPointerException,空指针异常
      • IllegalArgumentException,非法参数异常
    • RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。

捕捉异常时常用方法

  public static void main(String[] args) {
    int[] a=new int[2];
    try {
      for (int i = 0; i < 3; i++) {
        a[i]=i;
      }
    }catch (Exception e){
      System.err.println(e);
      //返回抛出异常的原因。如果 cause 不存在或未知,则返回 null。
      System.err.println(e.getCause());
      //返回异常的消息信息。
      System.err.println(e.getMessage());
      //对象的堆栈跟踪输出至错误输出流,作为字段 System.err 的值。
      System.err.println(e.getStackTrace());
    }
  }

在这里插入图片描述

处理异常机制

Java规定:对于可查异常(checked Exceptions)必须捕捉、或者声明抛出。允许忽略不可查的RuntimeException和Error。

简单地说,异常总是先被抛出,后被捕捉的

抛出异常

throws
  • 如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法声明处用throws子句来声明抛出异常。例如汽车在运行时可能会出现故障,汽车本身没办法处理这个故障,那就让开车的人来处理。

  • throws语句用在方法定义时声明该方法要抛出的异常类型,可以抛出多个异常类型

  • 方法将不对这些类型及其子类类型的异常作处理,而抛向调用该方法的方法,由他去处理。

  • 使用throws关键字将异常抛给调用者后,如果调用者无法处理该异常,可以继续向上抛出,但最终要有能够处理该异常的调用者。如pop方法没有处理异常NegativeArraySizeException,而是由main函数来处理。

  • import java.lang.Exception;
    public class TestException {
    	static void pop() throws NegativeArraySizeException {
    		// 定义方法并抛出NegativeArraySizeException异常
    		int[] arr = new int[-3]; // 创建数组
    	}
     
    	public static void main(String[] args) { // 主方法
    		try { // try语句处理异常信息
    			pop(); // 调用pop()方法
    		} catch (NegativeArraySizeException e) {
    			System.out.println("pop()方法抛出的异常");// 输出异常信息
    		}
    	}
     
    }
    
throw
  • throw总是出现在函数体中,用来抛出一个Throwable类型的异常。程序会在throw语句后立即终止,它后面的语句执行不到,
package Test;
import java.lang.Exception;
public class TestException {
	static int quotient(int x, int y) throws MyException { // 定义方法抛出异常
		if (y < 0) { // 判断参数是否小于0
			throw new MyException("除数不能是负数"); // 异常信息
		}
		return x/y; // 返回值
	}
	public static void main(String args[]) { // 主方法
		int  a =3;
		int  b =0; 
		try { // try语句包含可能发生异常的语句
			int result = quotient(a, b); // 调用方法quotient()
		} catch (MyException e) { // 处理自定义异常
			System.out.println(e.getMessage()); // 输出异常信息
		} catch (ArithmeticException e) { // 处理ArithmeticException异常
			System.out.println("除数不能为0"); // 输出提示信息
		} catch (Exception e) { // 处理其他异常
			System.out.println("程序发生了其他的异常"); // 输出提示信息
		}
	}
 
}
class MyException extends Exception { // 创建自定义异常类
	String message; // 定义String类型变量
	public MyException(String ErrorMessagr) { // 父类方法
		message = ErrorMessagr;
	}
 
	public String getMessage() { // 覆盖getMessage()方法
		return message;
	}
}

捕获异常

try、catch和finally
try {
	// 可能会发生异常的程序代码
} catch (Type1 id1) {
	// 捕获并处理try抛出的异常类型Type1
} catch (Type2 id2) {
	// 捕获并处理try抛出的异常类型Type2
} finally {
	// 无论是否发生异常,都将执行的语句块
}
  • try 块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
  • catch 块:用于处理try捕获到的异常。一旦某个catch捕获到匹配的异常类型,将进入异常处理代码。一经处理结束,就意味着整个try-catch语句结束。其他的catch子句不再有匹配和捕获异常类型的机会
  • finally 块:无论是否捕获或处理异常,finally块里的语句都会被执行。**当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。**在以下4种特殊情况下,finally块不会被执行:
    • 在finally语句块中发生了异常。
    • 在前面的代码中用了System.exit()退出程序。
    • 程序所在的线程死亡。
    • 关闭CPU。
执行顺序
  • 当try没有捕获到异常时:try语句块中的语句逐一被执行,程序将跳过catch语句块,执行finally语句块和其后的语句;
  • 当try捕获到异常,catch语句块里没有处理此异常的情况:此异常将会抛给JVM处理,finally语句块里的语句还是会被执行,但finally语句块后的语句不会被执行;
  • 当try捕获到异常,catch语句块里有处理此异常的情况
    • ①在try语句块中是按照顺序来执行的,当执行到某一条语句出现异常时,程序将跳到catch语句块
    • ②与catch语句块逐一匹配,找到与之对应的处理程序,其他的catch语句块将不会被执行,而try语句块中,出现异常之后的语句也不会被执行
    • ③catch语句块执行完后,执行finally语句块里的语句,最后执行finally语句块后的语句;

try、catch和finally中有return/throw

  1. finally有return/throw,会全面覆盖、替代掉catch里的return/throw。
  2. catch有return且finally无return,先执行 catch 中非 return 语句,再执行 finally 语句,最后执行 catch 中 return 语句。
  3. try有return语句,后续还有return语句,分为以下三种情况:
    1. 如果finally中有return语句,则会将try中的return语句”覆盖“掉,直接执行finally中的return语句,得到返回值,这样便无法得到try之前保留好的返回值。
    2. 如果finally中没有return语句,也没有改变要返回值,则执行完finally中的语句后,会接着执行try中的return语句,返回之前保留的值。
    3. 如果finally中没有return语句,但是改变了要返回的值,这里有点类似与引用传递和值传递的区别,分以下两种情况,:
      1. 如果return的数据是基本数据类型或文本字符串,则在finally中对该基本数据的改变不起作用,try中的return语句依然会返回进入finally块之前保留的值。
      2. 如果return的数据是引用数据类型,而在finally中对该引用数据类型的属性值的改变起作用,try中的return语句返回的就是在finally中改变后的该属性的值。
  • 14
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值