Java-异常

异常的概念
Java异常是指Java提供的用于处理程序错误的一种机制
所谓错误是指在程序运行的过程中发生的一些异常事件(例如访问的数组下标越界,读取的文件不存在)
设计良好的程序应该在异常发生日提供处理这些错误的方法,使得程序不会因为异常的发生而阻断或产生不可预见的结果
Java程序的执行过程中如果出现异常事件,可以生成一个异常类对象,该异常对象封装了异常事件的信息并将被提交给Java运行时系统,这个过程称为抛出(throw)异常
当Java运行时系统接收到异常对象时,会寻找能处理这一异常的代码并把当前异常对象交给其处理,这一过程称为捕获(catch)异常

这里我们通过一段程序来展示一下何为异常

public class TestEx {
	public static void main(String[] args) {
		int[] arr = {1 , 2 , 3};
			System.out.println(arr[3]);
			}

由于我们在对arr数组赋值的时候只开辟了三个空间,分别存入了1,2,3. 对应的数组下标分别为0,1,2
也就是说arr[3]这里访问的数组已经越界了,但是在编译阶段是不会发生错误提示了,而在执行阶段将会产生异常
在这里插入图片描述
这里简单解释一下,在我这个haro包里面的TestEx文件中的main第七行出现了异常,通过javalang这个方法中表示,3。 也就是说arr[3],这里出现了异常
通过这个小程序我们简单理解了异常的概念,但是遇到异常应该怎么办呢?

异常的捕获和处理
格式:

 try{
 }catch(SomeException1 e){
 ...
 }catch(SomeException2 e){
 ......} 
 finally{
 ...}
  • try代码段包含可能产生 例外的代码 try代码段后跟有一个或多个catch代码段
  • 每个catch代码段声明其能处理的一种特定类型的异常并提供处理的方法
  • 当异常发生时,程序会终止当前的流程,根据获取异常的类型去执行相应的catch代码段
  • finally段的代码无论是否发生异常都有执行

而这段程序的运行流程是这样的
在这里插入图片描述

  • try语句
    try{…}语句指定了一段代码,这段代码就是一次捕获并处理例外的范围
    在执行过程中,该段代码可能会产生并抛出一种或几种类型的异常对象,它后面的catch语句要分别对这些异常做相应的处理
    如果没有异常产生,所有的catch代码段都被略过不执行

  • catch语句
    在catch语句块中是对异常进行处理的代码,每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象
    在catch中声明的异常对象(catch(SomeException e))封装了异常事件发生的信息,在catch语句块中可以使用这个对象的一些方法获取这些信息
    例如:
    getMessage()方法,用来得到有关异常事件的信息
    printStackTrace()方法,用来跟踪异常事件发生时执行堆栈的内容

  • finally语句
    finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序其他部分以前,能够对程序的状态做统一的管理
    无论try所指定的程序块中是否抛出异常,finally所指定的代码都要被执行
    通常在finally语句中可以进行资源的清楚工作,例如:
    关闭打开的文件,删除临时文件等等

public class TestEx {
	public static void main(String[] args) {
		try {
			System.out.println(2/0);
		}catch (ArithmeticException ae) {
			System.out.println("卡了卡了");
			ae.printStackTrace();
		}

举一个简单的例子,当你承担了一个项目,在项目交接之后使用者某天突然发现系统不好使了,这时报错提示为一大堆专业术语就很麻烦了,为了改善这种事的发生,我们在catch语句中输出一条提示信息边可以得到解决
但catch()中的语句是什么意思呢?
它是把找到的异常对象存入ae中(ae仅仅是个名字),因为我们想要得到异常内部的信息,所以要定义该对象,也就是说ArithmeticException是方法的定义,而ae是形参,只有在try语句中产生异常,那么系统自动就会把ae的值给初始化
ae.printStackTrace()是打印出所有的堆栈信息,后期再讲
在这里插入图片描述

异常的分类
Error:称为错误,由Java虚拟机生成并且抛出,程序对其不做处理
Exception:所有异常类的父类,其子类对应了各种各样可能出现的异常事件,一般需要用户显式的声明或捕获
Runtime Exception:一类特殊的异常,其产生比较频繁,处理麻烦,用户可以不处理
在这里插入图片描述

我们再通过一段程序深入了解一下异常

public class TestEx {
	public static void main(String[] args) {
		try {
			System.out.println(2/0);
		}catch (ArithmeticException ae) {
			System.out.println("卡了卡了");
			ae.printStackTrace();
		}
		TestEx te = new TestEx();
		te.m(0);//当将0传入m方法便会抛出异常
		
	}
	void m(int i) throws ArithmeticException{//声明抛出的异常
		if(i==0)
			throw new ArithmeticException("被除数为0");//产生一个新的构造方法
	}
}

这里我们使用m方法来显式声明了抛出的异常,并且在m方法中还产生了一个新的构造方法,在main中进行了try catch操作之后,我们new出一个te,并且通过te调用m方法来抛出异常
在这里插入图片描述
但为什么会有两个异常呢,首先m方法中的异常是真真正正抛出异常的地方,而main类中调用的方法的异常,这就是将堆栈都打印出来,一个位置的异常会引起另一个位置的异常

我们这时对

		TestEx te = new TestEx();
		te.m(0);

这段语句换一种写法

		try {
			new TestEx().m(0);
		}catch(ArithmeticException ae) {
			ae.printStackTrace();
			System.out.println("出错了");
		}

对new出的TestEx()调用的m方法也进行一次try catch,看一下运行结果
在这里插入图片描述
这表明,这种异常我们可以选择不找出,但什么样的异常是必须要找出的呢?

FileInputStream in = null;
//在API中查询FileNotFoundException 不是Runtime类型的,所以必须得捕捉异常
try {
	in = new FileInputStream("myfile.txt");
	int b;
	b = in.read();
	while(b!= -1) {
		System.out.println((char) b );
		b = in.read();
	}
}catch(FileNotFoundException e) {
	e.printStackTrace();
}catch(IOException e) {
	System.out.println(e.getMessage());
}finally {
	try {
		in.close();
	}catch (IOException e) {
		e.printStackTrace();
	}
}

这里涉及到了一些I/O的知识,我们先不看那么多,只看关于异常的部分
在API中我们查到:public FileInputStream(File file)通过打开与实际文件的连接创建一个FileInputStream ,该文件由文件系统中的File对象file命名。 创建一个新的FileDescriptor对象来表示此文件连接。
由于我们这里将in设为null,此时就会产生FileNotFoundException异常
在这里插入图片描述
在对异常的分类中可以看到,RuntimeException类型的异常可以不必捕捉,通过API查到在这里插入图片描述
ArithmeticException正好在该类型下,所以可以选择不必捕捉

回归主题那到底什么样类型的异常必须被捕捉呢?
在这里插入图片描述
如果我们把这条语句放到try外边

in = new FileInputStream(“myfile.txt”);

这时就会暴露出问题

在这里插入图片描述
由此得知,在对异常进行分析的时候,需要通过API查找来确定是否需要捕捉异常

当我们遇到无法解决的异常时,需要怎么办呢?
Java的例外处理机制使得例外事件,沿着被调用的顺序往前寻找,只要找到符合该例外种类的例外处理程序即可解决
在这里插入图片描述

使用自定义异常
使用自定义异常一般有如下步骤:
1.通过继承java.lang.Exception 类来声明自己的异常类
2.在方法适当的位置生成自定义异常的实例,并用throw语句抛出
3.在方法的声明部分用throws语句声明该方法可能抛出的异常
等到后期需要用到的时候再细说

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值