java中的异常处理

异常的概念:程序运行时发生的不被期望的事件,其阻止了程序按照预期的执行。

java异常处理的关键字:throws、throw,try、catch、finally。

运行时有很多因素引起出错,如:硬件失败、除法溢出、数组下标越界等。
出错后方法生成一个Exception对象,并把它交给JVM。这个对象包括许多信息,如:错误类型、错误位置等。JVM负责处理Exception对象。

public class Test1{
	public static void main(String[] args){
		int k = 0;
		System.out.println(10/k);
		System.out.println("计算结果为:" + 10/k);
	}
}

运行结果为:

其中ArithmenticException为异常的一种类型,后面是异常说明。
生成Exception对象并交给系统的过程叫抛出意外(throwing an Exception)

public static void main(String[] args) throw Exception{//在方法上声明可能会出现的异常,由调用方进行处理
	int k = 0;
	if(k < 1)
		throw new Exception("这里有异常!!");//人为编程产生的异常
		System.out.println(10/k);
}

一个方法抛出异常后,JVM就试图调用栈里能找到的处理这个类型Exception对象的方法。找到就执行,找不到程序就中止。

将正常流程代码和问题处理代码分离。java中引入异常对象的目的在于给调用方更加详细的出错说明,以达到异常处理和正常代码分离,并且按照不同的异常进行处理的目的

异常是java通过面向对象的思想将程序中的问题封装成对象,用异常类对其进行描述。
不同问题用不同的类进行具体的描述。
问题很多意味着描述的类也很多,将其共性进行向上抽取就形成了异常体系。

java异常是java提供的用于处理程序中错误的一种机制。所谓错误是指在程序运行的过程中发生的一些异常事件。程序在执行过程中如果出现异常事件,可以生成一个异常类,该类对象封装了异常事件的信息并被提交给java运行时系统,这个过程称为抛出异常throw。
鲁棒性问题:当java运行时系统接受到异常对象时,代码的执行流程会自动中断,转向寻找能处理这一异常的代码,并把当前异常对象交给其处理,这个过程称为异常捕获。

异常的用途

异常就是在程序运行时由代码所产生的不正常状态,是一个运行时不支持异常处理的计算机语言,错误必须被人工进行检查和处理,但是这样麻烦且低效。

java提供了异常处理机制,为方法的异常终止和错误处理提供了清楚的接口。

  • 用来在发生运行异常时告诉程序如何控制自身的运行,以防止错误进一步
  • 每个方法必须对他可能抛出的异常进行预先声明,在定义方法时,必须声明这个方法可能会抛出哪一种或几种异常。
异常的分类

异常的分类
Throwable类是java异常类型的顶层父类,一个对象只有属于Throwable类的直接或者间接实例才是一个异常对象,才能被异常处理机制识别。

java异常分类

所有异常对象的父类Throwable-----Object

  • Error及其子类:错误一般是指虚拟机错误,是由java虚拟机生成并抛出,程序不能进行处理,所以也不加处理,。例如:OutOfMemoryError内存溢出、调用栈溢出StackOverFlowError
  • RuntimeException及其子类:运行时异常(非受检型异常),是由于编程bug导致的,不进行处理,直接中断报错即可,编程人员针对报错信息修改程序bug来解决问题。
  • 常见的运行时异常:ArithmeticException算数异常,NullPointerException空指针异常,IndexOutOfBoundsException下标越界,ClassCastException试图把一个对象转换成非法类型和NUmberFormatException数据格式异常(一般在数据类型转换中出现)
  • Exception及其子类中除了RuntimeException及其子类外的其他异常:非运行时异常(受检型异常),这类异常属于明知道可能会出现,但是没有办法杜绝的异常。这类异常一般采用try/catch或者throws声明抛出的方法进行异常处理。当程序出现非正常情况,要尽量保证程序的正常结果,而不是立即中断。
    受检型异常:明知道这种异常肯出现,但是没有办法杜绝,所以必须进行编码异常处理。
    非受检型异常:这种异常不需要进行处理,越早发现越好。
异常的捕获和处理
try{
	//try代码段中包含可能产生异常的代码,在执行过程中如果出现了异常,则异常之后的java语句不会执行。转而执行catch部分的代码
}catch(SomeException e){
	//try后面可跟一个或者多个catch代码段,针对不同异常执行不同处理。当异常发生时,程序会中止当前的流程,根据获取异常的类型去执行相应的代码段。一个catch被执行后,后面若还有catch之后的catch不再执行,异常类的判定是从上向下逐个判断的,前面的catch范围要小于后面的catch范围
}finally{
	//无论代码是否发生异常、发生何种异常,finally里的东西都会执行
}
  • try块中的局部变量、catch块中的局部变量(包括异常变量)和finally中的局部变量之间是不可共享的。
  • java采用的是终结式异常处理机制,异常处理的任务就是将执行控制流从异常发生的地方转移到能够处理这种异常的地方。当一个函数的某条语句发生异常时,这条语句的后面的语句不会再执行,失去的焦点。执行流跳转到最近的匹配的异常处理catch代码块去执行,异常被处理完之后执行流会接着在“处理了这个异常的catch代码块”后面接着执行(但是只能执行一个catch代码块)。
  • try{}后面必须跟一个catch或finally,try后面可以紧邻0-n和catch,如果没有catch则必须紧邻finally。
public static void main(String[] args){
	for(int i = 0;i<10;i++)
		System.out.println(i);
	System.out.println(i);
	try{
		FileInputStream fis = new FileInputStream("c:/cc.data");
	}catch(Exception e){
		System.out.println(e);
	}finally{
		System.out.println("读完了!")
	}
	System.out.println(e);
}
异常处理
  • try:用于监听。将要被监听的代码(可能会出现异常的代码)放在try语句块内,当try语句块内发生异常时,异常就被抛出。
  • catch:用于捕获异常。catch用来捕获try语句块中发生的异常。
  • finally:finally语句块总会被执行,它主要用于回收在try里面打开的资源(如数据库连接、网络连接和磁盘文件等)。只有finally块执行完成后,才会执行try或者catch块中的return或者throw语句。如果finally中使用了return或者throw等终止方法,则就不会跳回执行,直接停止。
  • throw:人为编程实现抛出异常
  • throws:用在方法签名中,用于声明该方法可能抛出的异常,要求谁调用谁处理这个异常。主方法上也可使用throws抛出,表示主方法里面可以不用强制性进行异常处理,如果出现了异常,就交给JVM进行默认处理,则此时会中断程序执行。
try语句

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

catch语句

在catch语句块中是对异常进行处理的代码,每个try语句可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象,同时允许异常的继续抛出。
catch只匹配成功一次即可,不是最佳匹配。编写多个catch时,小异常一定要在大异常之前
在catch中声明的异常对象封装了异常发生的信息没在catch语句块中可以使用这个对象的一些方法获取这些信息。

  • getMessage():String用于获取有关异常事件的信息,一般都是异常信息的描述。eg :[For input string:“666.66”]
try{
	String ss = sc.nextLine();
	int hh = Integer.parseInt(ss);
}catch(Exception e){
	System.out.println(e.getMessage());
}
  • to String():String,输出格式为:[java.lang.NumberFormatException:For input string “666.66”]
try{
	String ss = sc.nextLine();
	int hh = Integer.parseInt(ss);
}catch(Exception e){
	System.out.println(e);
}
  • printStackTrace():void用来跟踪异常事件发生时执行堆栈的内容。这里输出默认采用错误流System.err进行输出,他如果使用System.out则不保证显示顺序。
public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
	try{
		String ss = sc.nextLine();
		int hh = Integer.parseInt(ss);
	}catch(Exception e){
		System.out.println("异常处理");
		e.printStackTrace();
	}
	System.err.println("结束了");
	sc.close;
}

使用printStackTrace输出调用栈使用的是System.err输出报错信息,不是编程使用的System.out,所以输出顺序有可能和预估不一致。

常见的三种输出异常的方法
  • System.out.println(e);//java.lang.ArithmeticRxception:/by zero
  • System.out.println(e.getMessage());// /by zero
  • e.printlnStackTrace();调用栈 syserr
    大部分情况下肯会出现多种不同异常但是处理方法一致,多个异常类型之间没有继承关系,如果有继承关系,则应该写成try{}catch(父类型e){}。
    eg:
try{
......
}catch(RuntimeException e){
	System.out.println(e);
}catch(Exception e){
	System.out.println(e);
}catch(Throwable e){
	System.out.println(e);
}

如果两次捕获对异常的处理时一样的,就可以将两个异常卸载一个catch,其中多个异常类型之间使用|分割。
如:

try{
......
}catch(IOException | SQLException e){
	System.out.println(e);
}

可以有多个catch,但是要有从小到大的顺序。如果先大后小,则小代码不可及。

  • 可以使用定义多个catch语句捕获不同的异常,采用不同的处理方式,但是一般还是不要使用catch作为程序处理分支
  • catch可以消费异常,这个异常被消费后不再提交运行时环境处理。
  • 大异常在前小异常不可达。
finally语句

finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序的其他部分以前,能够对程序的状态做统一管理。

  • 无论try所指定的程序块是否抛出异常,finally所指定的代码都要执行
  • try可以没有catch而直接使用finally,在方法上声明抛出。
    通常在finally语句中可以进行资源的清楚工作,如:关闭打开的文件、删除临时文件等。java的垃圾回收机制只能回收在堆内存中对象所占用的内存,而不会回收任何物理资源,如:数据库连接、网络连接等。
特殊情况导致finally执行出现问题
  • 在前面的代码中使用System.exit(int)退出应用
    终止当前运行的java虚拟机 。int参数用作状态代码,按照惯例,非零状态代码表示异常终止。
  • 程序所在的线程死亡或者cup关闭
  • 如果finally代码块中的操作产生异常,则该finally代码块不能完全执行结束。
finally、final和finalize的区别
  • finally关键字在java中代表不可改变的,可以用来修饰类、方法和变量。
    对于class:用final修饰类表示该类不能被继承,没有子类与接口实现。因此一个类既被声明为abstract又被声明为final。
    对于方法来说:如:public final void Mod(){}表示此方法不能被重写。
    对于变量来说,必须在声明前赋值,且不能再改变。
  • finally关键字用在异常处理中,用于处理异常后的清理工作,实际中一般用于关闭文件流,释放资源等。
  • finalize(方法名)。java允许使用finalize()方法在垃圾收集器对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的,它是在Object类中定义的,因此所有类都继承它,子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。finalize()方法是在垃圾回收器删除对象之前对这个对象调用的。
    异常树
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值