异常

概念

Java的基本概念是”结构不佳的代码不能运行”。发现错误的理想时机是在编译阶段,也就是在我们试图运行程序之前。然而,编译期间并不能找出所有的错误,余下的问题必须在运行期间解决。因此通过引进异常机制,处理错误。

异常体系

在这里插入图片描述
在Java中,异常主要分为两类,Exception和Error,这两类都有一个共同的父类Throwable类。
Error:该异常往往是一些比较严重的异常,并且这种异常不可捕获,是一种程序无法处理的错误,例如内存不够用时的 OutOfMemoryError、Java 虚拟机运行时错误(VirtualMachineError)。
Exception:这种异常是可以捕捉的,写程序时能够预测到的,所以这种异常是程序本身可以处理的。Exception 有一个比较重要的子类就是 RuntimeException,常见的具体错误有 空指针(NullPointerException),数组访问越界等

基本异常

异常情形是指阻止当前方法或作用域继续执行的问题。在遇到无法解决的问题时,选择从当前环境跳出,并且把问题提交给上一级环境,这就是抛出异常。首先,同java其他对象的创建一样,抛出异常时将使用new在堆上创建异常对象;接着当前执行路径被终止,并且从当前环境中弹出对异常对象的引用。此时,异常处理机制接管程序,并开始寻找一个恰当的地方继续执行程序,这个恰当的地方就是异常处理程序,它的任务就是将程序从错误状态中恢复,以使程序换一种方式运行,要么继续运行下午。

异常参数

与其他对象相同,在堆上new对象,伴随着存储空间的分配以及构造器的调用。所有的标准异常类都有两个构造器,一个默认构造器,一个是接收字符串参数的构造器。
throw new NullPointerException(“error”)

捕获异常

try块
如果在方法内部抛出了异常,这个方法将在抛出异常的过程中结束。要是不希望方法就此结束,可以在方法内部设置一个特殊的块来捕获异常,称为try块。
举个栗子:
int i=10/0;
这段代码如果没有放在try块中,出现异常会直接导致程序崩溃,无法再运行下去。而try可以保证程序正常运行下去。(出现异常错误信息时,将错误信息存储到Exception)

异常处理程序
前面讲到发生异常时,将错误信息存储到Exception中。抛出的异常必须在某处得到处理,这个地点就是异常处理程序。异常处理程序紧跟在try块后,以关键字catch表示。
异常处理程序必须紧跟在try块后,当异常抛出时,异常处理机制负责搜寻参数与异常类型相匹配的第一个处理程序,然后进入catch子句执行。

finally 块:无论是否捕获或处理异常,finally块里的语句都会被执行。当在try块或catch块中遇到return语句
时,finally语句块将在方法返回之前被执行。

特别注意,finally块以下情况下不会被执行:

  1. 在finally语句块中发生了异常
  2. 在前面的代码中用了System.exit()退出程序
  3. 程序所在的线程死亡
  4. 关闭CPU

捕获所有异常
catch(Exception e){}使用异常基类Exception捕获所有异常

创建自定义异常

自己定义异常类,必须从已有的异常类继承(一般继承Throwable或者它的子类Exception)。
在这里插入图片描述

自定义异常如何使用

自定义test1()方法,抛出异常信息,test2()调用test1()方法,并将异常包装成RuntimeException类型的异常继续抛出。
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

此时的疑惑:
test1()方法中抛出异常,并且test1()方法自己没办法处理异常,所以在参数列表后将异常抛出。test2()调用test1()捕获其异常,并将其包装成RuntimeException异常继续抛出,但是test2()方法却没有声明异常,而且在mian中调用test2(),也不用try-catch代码块去捕获异常。

插入讲下checked异常和RuntimeException(运行时异常)

什么是运行时异常?

程序在运行过程中出现的异常,RuntimeException是Exception的一个子类。
运行异常的特点:
一般来说,我们在方法体内出现异常,我们用throw关键字将异常对象或异常对象的引用抛出,如果当前方法无法处理该异常,那么必须在方法的参数列表后面用throws声明异常所属类,交给调用者去处理。但是RuntimeExcepetion是非常特殊的子类,你可以不用throw和throws,哪怕你throw了,也可以不用throws,即使你throws,调用者也没必要tyr-catch。
-如果在函数内容上抛出该类异常或其子异常,函数上可以不用声明
-在函数上声明该异常,调用者可以不用处理try-catch

为什么不用声明?
之所以不用声明,是因为不需要让调用者处理。当该异常发生时,希望程序停止。
如何运用运行时异常?
自定义异常时,如果希望该异常的发生会导致程序无法继续运行,那么就让自定义异常去继承RuntimeException

运行时异常和check异常的区别?
检查异常:编译时被检查的异常(throw后,方法有能力处理就try-catch,没能力处理就throws)
运行时异常:编译时不被检查的异常(RuntimeException及其子类)

常见面试题

Error和Exception区别是什么?

Error类型的错误通常为虚拟机相关错误,如系统崩溃,内存不足,堆栈溢出等,编译器不会对这类错误进行检测,JAVA应用程序也不应对这类错误进行捕获,一旦这类错误发生,通常应用程序会被终止,仅靠应用程序无法恢复。
Exception类的错误是可以在应用程序进行捕获并处理的。

运行时异常和一般异常区别是什么?

编译器不会对运行时异常进行检测,没有try-catch,方法签名没有throw exception,编译依然可以通过

NoClassDefFoundError和ClassNotFoundException区别是什么?

NoClassDefFoundError是一个Error类型的异常,是由JVM引起的,不应该尝试捕获这个异常。引起该异常的原因是JVM或ClassLoader尝试加载某类时在内存中找不到该类的定义。
ClassNotFoundException是一个受查异常,需要显氏地使用try-catch对其进行捕获和处理,或在方法签名用throws声明。引起该异常的原因是通过Class.forName,ClassLoader.loadClass动态加载类到内存中时,通过传入的类路径参数没有找到该类,就会抛出该异常;另一种可能是某个类已经由一个类加载到内存中,另一个加载器又尝试加载它。

JVM是如何处理异常的?

在一个方法中如果发生异常,这个方法会创建一个异常对象,并转交给JVM。该异常对象包含异常名称,异常描述以及异常发生时应用程序的状态。创建异常对象并交给JVM的过程,称为抛出异常。抛出异常的过程中可能经过一系列方法调用,这一系列方法调用的有序列表称为调用栈。JVM会顺着调用栈去查看是否有可以解决异常的代码,如果有,则调用异常处理代码。如果没有JVM会交给默认的异常处理器,默认处理器打印出异常信息并终止应用程序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值