【Java编程进阶之路--异常处理】

活动地址:[CSDN21天学习挑战赛](https://marketing.csdn.net/p/bdabfb52c5d56532133df2adc1a728fd)


前言

异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。
异常发生在程序运行期间,它影响了正常的程序执行流程。
异常发生的原因有很多,通常包含以下几大类:

  • 用户输入了非法数据。
  • 要打开的文件不存在。
  • 网络通信时连接中断,或者JVM内存溢出

异常指不期而至的各种状况,如:文件找不到、网络连接失败、除0操作、非法参数等。异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程。

一、异常体系

Java把异常当作对象来处理,并定义一个基类 java.lang.Throwable 作为所有异常的超类。

Java异常层次结构图:

在这里插入图片描述
在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception

1、Error

Error 类对象由Java虚拟机生成并抛出的,大多数错误与代码编写者所执行的操作无关。
例如:

Java虚拟机运行错误( Virtual MachineError ),当JVM不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError 。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止;

2、Exception

在 Exception 分支中有一个重要的子类 RuntimeException (运行时异常),该类型的异常自动为你所编写的程序定义 ArrayIndexOutOfBoundsException (数组下标越界)NullPointerException (空指针异常)、ArithmeticException`` (算术异常)、 MissingResourceException (丢失资源)、 ClassNotFoundException` (找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。

这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;而RuntimeException 之外的异常我们统称为非运行时异常,类型上属于 Exception 类及其子类。
IOException SQLException 等以及用户自定义的 Exception 异常, 如果不处理,编译不能通过。

注意:
Error 通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;
Exception 通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。

3. 检查异常和不受检查异常

不受检查异常 为编译器不要求强制处理的异常, 检查异常 则是编译器要求必须处置的异常,在正常的程序运行过程中,很容易出现,情理中的异常,在一定程度上可以预测到这种异常,一旦发现必须要采取某种方式进行处理。

除了RuntimeException及其子类以外,其他的Exception类及其子类都是属于检查异常。
当程序中可能出现这类异常,要么使用try-catch语句进行捕获,要么用throws子句抛出,否则编译无法通过。
不受检查异常:包括RuntimeException及其子类和Error。

二、异常处理机制

1.抛出异常

异常处理五个关键字
分别是: try 、 catch 、 finally 、 throw 、 throws
try – 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
catch – 用于捕获异常。catch用来捕获try语句块中发生的异常。

关键词 try 后的一对大括号将一块可能发生
异常的代码包起来,即为监控区域。Java方法在运行过程中发生了异常,则创建异常对象。
—>若有一个catch 语句匹配到了,则执行该 catch 块中的异常处理代码,就不再尝试匹配别的 catch 块

finally – finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
throw – 用于抛出异常。
有两种方法可以获取 Throwable 对象:

  • 在 catch 子句中使用参数或者使用 new 操作符创建。程序执行完 throw 语句之后立即停止;
  • throw 后面的任何语句不被执行,最邻近的 try 块用来检查它是否含有一个与异常类型匹配的 catch 语句。如果没有发现匹配的 catch 块,默认异常处理程序中断程序的执行并且打印堆栈轨迹。
    throw new NullPointerException("demo");

throws – 用在方法签名中,用于声明该方法可能抛出的异常。
如果一个方法可以导致一个异常但不处理它,它必须指定这种行为以使方法的调用者可以保护它们自己而不发生异常。
throws 抛出异常的规则:

  1. 如果是不受检查异常( unchecked exception ),即 Error 、 RuntimeException 或它们的子类,那么可以不使用 throws 关键字来声明要抛出的异常,编译仍能顺利通过,但在运行时会被系统抛出。
  2. 必须声明方法可抛出的任何检查异常( checked exception )即如果一个方法可能出现受可查异常,要么用 try-catch 语句捕获,要么用 throws 子句声明将它抛出,否则导致编译报错
  3. 仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。
  4. 调用方法必须遵循任何可查异常的处理和声明规则。
    【出动抛出异常】
    是像创建普通的java对象一样将使用 new 在堆上创建一个异常对象;然后,当前的执行路径(已经无法继续下去了)被终止,并且从当前环境中弹出对异常对象的引用。

这个恰当的地方就是异常处理程序或者异常处理器,它的任务是将程序从错误状态中恢复,以使程序要么换一种方式运行,要么继续运行下去。

//避免程序中断,提高代码的可用性
//假设这方法中,处理不了这个异常,方法上抛出异常
try{
    
    
  System.out.println("a/b的值是:" + 1 / 0);
}catch(Error e){
    
    // catch(想要捕获的异常) 等级高的异常放在后面
 //the code of handling exception1 
 }
 
public void text() throws ArithmeticException(){
    
    
	if(b==0){
    
    
	throw new ArithmeticException();//在方法内主动抛出异常
  }
}

try–catch 是遇到错误也能运行,throws和throws是运行时候给抛出异常。

2.处理异常

//捕获异常多个,从小到大
try{
    
    
System.out.println("a/b的值是:" + 1 / 0);
}catch(Error e){
    
    // catch(想要捕获的异常) 等级高的异常放在后面
 //the code of handling exception1 
 }catch(Exception e){
    
    
  //the code of handling exception2 }
  }catch(Throwable e){
    
    
  e.printStackTrace();//打印错误的栈信息
   //the code of handling exception3 }
//等级exception1 《exception2 《exception3
finally {
    
    
	//处理善后工作,可以不要,假如IO流,资源关闭就需要了
}

关键词 try 后的一对大括号将一块可能发生
异常的代码包起来,即为监控区域。Java方法在运行过程中发生了异常,则创建异常对象。


public class TestException {
    
    
 public static void main(String[] args) {
    
     
 int a = 1; int b = 0; 
 try {
    
     // try监控区域 
 if (b == 0) throw new ArithmeticException(); // 通过throw语句抛出 异常 
	 System.out.println("a/b的值是:" + a / b); 
	 System.out.println("this will not be printed!"); 
 }catch (ArithmeticException e) {
    
    
  // catch捕捉异常 
   System.out.println("程序出现异常,变量b不能为0!"); 
  }finally {
    
    
    System.out.println("程序正常结束。");
  }
   } }

//输出 
程序出现异常,变量b不能为0!
 程序正常结束。

算术异常属于运行时异常,因而实际上该异常不需要程序抛出,运行时系统自动抛出。如果不用try-catch程序就不会往下执行了。


catch (ArithmeticException e) {
    
     
// catch捕捉异常 
System.out.println("程序出现异常"+e);
 }
 //输出 
 程序出现异常java.lang.ArithmeticException
 程序正常结束。

3. 自定义异常

使用Java内置的异常类可以描述在编程时出现的大部分异常情况。用户还可以自定义异常,只需继承 Exception 类即可
寻找异常类快捷键:双击 + shift
用户自定义异常类,只需继承 Exception 类即可。
在程序中使用自定义异常类,大体可分为以下几个步骤:

  • 创建自定义异常类。
  • 在方法中通过 throw 关键字抛出异常对象。
  • 如果在当前抛出异常的方法中处理异常,可以使用 try-catch 语句捕获并处理;否则在方法的声明处通过 throws 关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
  • 在出现异常方法的调用者中捕获并处理异常。

【自定义测试异常】

//定义的异常类
class MyException extends Exception {
    
     
    private int detail; //传递数字 > 10;
public	MyException(int a){
    
     
	    this.detail = a; 
}
//toString :异常打印信息
public String toString(){
    
    //alt + insert 重写方法
	 return "MyException ["+ detail + "]"; 
	 } 
 }

// 测试异常
public class Test{
    
    
	static void test(int a)throws MyException {
    
    
		System.out,print("传递的参数"+a);
	if(a>10){
    
    
		throws new MyException(a);
		}
		System.out.println("Normal exit!");
	}
	
	public static void main(String [] args)	
	{
    
    
		try{
    
    
		  test(1);
		  test(20);
		}catch(MyException me){
    
     
		System.out.println("Caught " + me);
      }	 
     }
}


//输出
 Called compute(1)
 Normal exit!
 Called compute(20)
 Caught MyException [20]

总结创作不易,动手一键三连吧~

在这里插入图片描述

  1. 处理运行时异常,采取逻辑合理规避同时辅助try-catch处理
  2. 在多重catch后面,可以加多一个catch(Exception)来处理被遗漏的异常。
  3. 对不确定的代码,加上try-catch,处理潜在的异常。
  4. 调用printStackTrace()去打印输出。
  5. 尽量添加finally语句去释放占用的资源。

猜你喜欢

转载自blog.csdn.net/m0_53142039/article/details/126316657