Java异常分类处理与Scala异常处理

异常体系

        异常体系

在Java语言中, 将程序执行中发生的不正常情况称为“异常” 。
(开发过程中的语法错误和逻辑错误不是异常)
Java程序在执行过程中所发生的异常事件可分为两类:

Error: Java虚拟机无法解决的严重问题。 如: JVM系统内部错误、 资源耗尽、断电、网络中断、内存不够等情况。
比如: StackOverflowError和OOM。 一般不编写针对性的代码进行处理。
Exception: 其它因编程错误或偶然的外在因素导致的一般性问题, 可以使用针对性的代码进行处理。 例如:
        1、空指针访问
        2、试图读取不存在的文件
        3、网络连接中断
        4、数组角标越界

Exception又可以分为两类:

         运行时异常:RuntimeException

是指编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该积极避免其出现的异常。 java.lang.RuntimeException类及它的子类都是运行时异常。
对于这类异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响。

        编译时异常:

是指编译器要求必须处置的异常。即程序在运行时由于外界因素造成的一般性异常。
编译器要求Java程序必须捕获或声明所有编译时异常。
对于这类异常,如果程序不处理,可能会带来意想不到的结果

异常产生原因

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

Error与Exception的区别:

Error(错误)是系统中的错误,程序员是不能改变的和处理的,是在程序编译时出现的错误,只能通过修改程序才能修正。一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和和预防,遇到这样的错误,建议让程序终止。

Exception(异常)表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。

常见异常

编译异常

异常描述
ArithmeticException当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例
ArrayIndexOutOfBoundsException  用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。
ArrayStoreException试图将错误类型的对象存储到一个对象数组时抛出的异常。
IllegalArgumentException    抛出的异常表明向方法传递了一个不合法或不正确的参数。
IllegalMonitorStateException    抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程
IllegalThreadStateException    线程没有处于请求操作所要求的适当状态时抛出的异常。
IndexOutOfBoundsException    指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。
NegativeArraySizeException    如果应用程序试图创建大小为负的数组,则抛出该异常。
NullPointerException    当应用程序试图在需要对象的地方使用 null 时,抛出该异常
NumberFormatException    当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
SecurityException    由安全管理器抛出的异常,指示存在安全侵犯。
StringIndexOutOfBoundsException  此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。
UnsupportedOperationException    当不支持请求的操作时,抛出该异常。

运行时异常

ClassNotFoundException    应用程序试图加载类时,找不到相应的类,抛出该异常。
CloneNotSupportedException    当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。
IllegalAccessException    拒绝访问一个类的时候,抛出该异常。
InstantiationException当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。
InterruptedException   一个线程被另一个线程中断,抛出该异常。
NoSuchFieldException    请求的变量不存在
NoSuchMethodException  请求的方法不存在

处理异常方式

方式一: try-catch-finally

try

捕获异常的第一步是用 try{…} 语句块选定捕获异常的范围, 将可能出现异常的代码放在try语句块中。在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配。 一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常处理,一旦处理完成就跳出当前的try-catch结构(在没有写finally的情况下)。继续执行其后的代码。在try结构中声明的变量,出了try结构之后,就不能被调用。

catch (Exceptiontype e)
在catch语句块中是对异常对象进行处理的代码。 每个try语句块可以伴随一个或多个catch语句, 用于处理可能产生的不同类型的异常对象。catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓,如果异常类型满足子父类的关系,则要求子类一定要声明在父类的上面,否则报错。

finally
捕获异常的最后一步是通过finally语句为异常处理提供一个统一的出口,使得在控制流转到程序的其它部分以前,能够对程序的状态作统一的管理。
不论在try代码块中是否发生了异常事件, catch语句是否执行, catch语句是否有异常, catch语句中是否有return,finally块中的语句都会被执行。
finaly中声明的是一定会被执行的代码,即使catch中出现了异常,try中有return语句,catch中有return语句等情况。
finally语句和catch语句是任选的。
像数据库连接,输入输出流,网络编程socket等资源,JVM是不能自动回收的,我们需要手动的进行资源的释放。此时的资源的释放,就需要声明在finally中

 finally和return

在无返回值方法中,return在对finally的访问后执行

在有返回值的方法中,如果finally中有return值,那么一定会执行finally的return

如果finally中没有return,也在return后再访问finally

要求必须被处理exception 不是必须RuntimeException

方式二: throws + 异常类型

声明抛出异常是Java中处理异常的第二种方式

throws +异常类型,写在方法的声明处,此时此方法执行时, 可能会抛出的类型。
如果一个方法(中的语句执行时)可能生成某种异常, 但是并不能确定如何处理这种异常, 则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。
在方法声明中用throws语句可以声明抛出异常的列表, throws后面的异常类型可以是方法中产生的异常类型, 也可以是它的父类。
一旦方法体执行时,出现异常,仍会在异常代码处,生成一个异常类的对象,此对象满足throws后异常类型是,就会被抛出。异常代码后续的代码,就不在执行。
throws的方式只是将异常抛给了方法的调用者,并没有真正将异常处理掉。

throw和throws

throw和throws都是在异常处理中使用的关键字,区别如下:

  • throw:指的是在方法中人为抛出一个异常对象(这个异常对象可能是自己实例化或者抛出已存在的);
  • throws:在方法的声明上使用,表示此方法在调用时必须处理异常。

自定义异常类型

一般地,用户自定义异常类都是RuntimeException的子类。
自定义异常类通常需要编写几个重载的构造器。
自定义异常需要提供全局常量:serialVersionUID
自定义的异常通过throw抛出。
自定义异常最重要的是异常类的名字,当异常出现时,可以根据名字判断异常类型。

用户自定义异常类MyException,用于描述数据取值范围错误信息。用户自己的异常类必须继承现有的异常类

案例:

先继承已知的异常类型,一般是Exception或RuntimeException

然后用super引用父类的有参构造(String message)

在setAge内抛出异常,main方法内处理异常

 Scala异常处理

Scala的异常的工作机制和Java一样,但是Scala没有“checked(编译期)”异常,即Scala没有编译异常这个概念,异常都是在运行的时候捕获处理。

Scala中捕捉异常的catch子句,语法与其他语言中不太一样。在Scala里,借用了模式匹配的思想来做异常的匹配,因此,在catch的代码里,是一系列case字句
try中的代码是我们编写的业务处理代码,在catch中表示当出现某个异常时,需要执行的代码
在finally中,是不管是否出现异常都会执行的代码

package com.robot.scalademo
 
object _08ObjectDemo {
 
  def main(args: Array[String]): Unit = {
    try {
      val i = 10 / 0
 
      println("你好!")
    } catch {
      //case ex: Exception => println(ex.getMessage)  //   / by zero
      case ex:Exception => ex.printStackTrace()  //调用自带方法打印,case只执行一个。
    }
    finally {
      println("我一定会执行,不管异常上面发生了什么")
    }
  }
}
/***
 java.lang.ArithmeticException: / by zero
	at com.robot.scalademo._08ObjectDemo$.main(_08ObjectDemo.scala:7)
	at com.robot.scalademo._08ObjectDemo.main(_08ObjectDemo.scala)
  我一定会执行,不管异常上面发生了什么
  */


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值