1. 什么是Java异常?java
今天咱们来聊聊java异常,异常是致使程序中断执行的一种指令流。咱们在提升代码稳定性和健壮性的时候,经常会花更多的时间去考虑,代码可能存在的异常。编码中对可能的发生的异常先一步正确处理,就能够确保异常不会致使程序不可用。说了这么多异常,那么异常是什么呢?程序员
Java异常是一种致使程序中断的执行指令流。它存在应用服务器硬件错误、程序编写的时候未考虑数组越界、也多是网络通讯中网络抖动的客观缘由致使的异常等状况。异常多是主观代码设计不周全也多是客观硬件报错,那么认识异常就是避免异常的第一步。咱们先从异常家族的认识开始,下面异常的族谱:数据库
Throwable类做为全部异常的发源,他是整个Java异常体系的超体,其下面分为Error和Exception两大类。编程
Error与其子类实例表明严重系统错误,应用程序没法处理,如硬件层面的错误、JVM错误或内存不足等问题,这种错误发生时Java应用程序自己无力恢复。Error对象抛出时,基本上不用处理,任其传播至JVM为止,应用程序能作的最多留下日志信息。数组
Exception表明程序运行时发送的各类不指望发生的事件。能够被Java异常处理机制使用,是异常处理的核心。Exception及其子类能够被程序处理,也就是所在应用程序中正确的处理了Exception及其子类就能提升代码的稳定性和健壮性。服务器
Exception类下面分为检测异常和非检测异常:网络
检测异常,是JVM强制要求程序员为可能出现的异常作预备处理工做。JVM规定检测异常要么使用try-catch语句捕获它并进行处理,要么使用throws子句声明并抛出它,否者javac在编译程序会不经过。这类异常通常是程序运行环境致使的,为了预防未知环境对程序的影响,规定程序员须要处理这类异常。函数
非检测异常,javac在编译时,不会提示和发现异常的存在,JVM不强制要求程序员处理这样的异常。固然,做为程序员咱们应该预防这样的异常致使程序崩溃,因此建议使用try-catch-finally处理它。这类异常缘由多半是代码写的逻辑有问题或考虑不周全。编码
2.当一个Exception在程序中发生的时候,JVM是怎么作的呢?spa
对java总体异常家族有了大体的认识以后,那么当一个Exception在程序中发生的时候,JVM是怎么作的呢?
认识这个问题,咱们首看看JVM是如何执行java代码的,JVM将class文件转换为JVM的java类。JVM为java类创建方法表,方法表中的索引能够引导JVM找到须要执行的方法体和JVM方法执行栈。固然,invokemethod调用执行一个方法的时候,Java虚拟机把描述该方法的栈结构置入方法执行栈栈顶,位于栈顶的方法为正在执行的方法。 JVM会为每个方法创建执行的堆和栈用于存放执行中的变量,若是此时程序出现一个Exception,抛出的异常先转移给合适的异常处理语句。代码的执行会被相应的Exception执行流接管,将方法表信息、发生异常的位置信息和方法的堆栈信息压入Exception的堆栈,当程序中断的时候IDE就会将Exception的堆栈信息打印出来。
若是咱们经过try…..catch….finally语句来处理异常,处理流程又是怎样的呢?在try代码块中抛出的异常,代码执行流会跳转到catch代码块执行,catch代码块能够对发生的异常进行补救。让代码回归到正常的执行流程。finally语句,不管在try模块中是否发生异常,都会执行finally语句,使用finally语句主要是为了释放被占用的资源,好比打开的文件或连接的通讯资源等。
整体来讲,Java语言的异常处理流程,从程序中获取异常信息。根据Java的源文件和用户调用的包列表,JVM能够获取该程序包括Java API所引起的异常在内的异常处理的信息,这些信息包括:异常引起位置、异常抛出顺序、引起异常的方法名和类名等。这些异常信息在程序异常的排查和修改的时候很是重要,后面会讲到如何正确处理这些异常。
3.当咱们编写程序的时候如何对待可能出现的异常呢?
一般在发生异常的时候咱们有两种处理模型:终止与恢复。
终止模型:前提是假设错误很是关键,以致于程序没法返回到程序正常运行轨迹,一旦异常抛出就意味着程序将中止提供服务。如:数据库链接异常发生。
恢复模型:也就是异常程序发生错误,错误能够被修复而后从新回到正常程序执行的轨迹上。例如,咱们能够将数据库链接try。。。catch置于循环中,一次链接不成功能够循环下一次进行链接。
配合终止和恢复模型,咱们会配合使用throw和throws语法。throws关键字主要在方法签名中使用,用于声明该方法可能抛出的异常。throws 能够理解成是一种通知行为,没有实际的抛出异常的动做,而仅仅是告诉调用他的上层函数,这里可能会抛出这个异常;
throw用于在函数体内语句中,表示抛出一个实际的异常的实际动做,若是在函数内没有捕获并处理,那么将会一直向上抛出这个异常直到被main()/Thread.run()抛出。
咱们了解了Java的异常内容以后,在程序中遵循怎样的行业规则和大牛的经验合理使用异常,提升代码的稳定性呢?
下面整理了包括Effective Java异常使用指导原则和网上博客内容:
不要被这么多规则吓到了,不须要逐条强记他们。我对异常的理解,首先态度上要谦虚明白代码中很难避免由于考虑不周出现的异常,因此编码时应该采用防卫式编码。其次在编码处理过程当中使用try…catch…finally语句预防可能的异常,采用合适的异常处理模式对待程序可能的异常。