Java中应用程序在非正常的情况下停止运行主要包含两种方式: Error 和 Exception ,像我们熟知的 OutOfMemoryError 和 IndexOutOfBoundsException 等。在日常的开发过程中 Error 我们是不用处理的,一旦 Error 发生必然证明应用程序代码上出现了问题,这个时候我们只能是修改代码。而 Exception 则是在程序运行的过程中可以进行捕获并处理的。接下来的所有讨论均会以 Exception 为主。

异常的继承图

所有的异常均继承在 Exception 类,而在其子类中又分为运行时异常RuntimeException 和 其他的异常类。所谓的运行时异常指的是在运行的时候所抛出的异常,例如:IndexOutOfBoundsException 就是 RuntimeException 的子类,访问数组下标范围外的元素,在代码的编译时期是无法被检测到的,只有在运行的时候才会抛出这样的异常。其他的异常则是 Exception 的直接子类,这些异常也可以称为编译时异常,编译时异常虽然是运行时被抛出的,但是在代码编写的过程中就会知道某些代码可能会抛出异常,并需要对其作出反应:处理或者是继续向上一层调用栈抛出。他们的主要区别可以用一句话来总结:编译时期可以发现并且需要对其作出反应的异常为编译时异常,在编译时期不能发现的异常叫运行时异常。当运行时异常发生的时候,也意味着我们是需要调整我们的代码的。在下面讨论 throws 关键字的时候会详细说明。

throw 异常的可抛性

所有的异常均可以使用 throw 关键字主动抛出,但 throw 并不能抛出一切东西,例如我们无法使用 throw 抛出一个数组或者是一个 Interger 实例。异常具有可抛性是因为 Exception 的父类是 Throwable ,只有继承它,才具有可抛性。这一点作为了解就可以了,在Java内部已经为我们定义了很多的异常,如果感觉内置的异常无法满足要求,我们也可以通过继承自`Exception 或 RuntimeExcetpion 来扩展异常。

throws 异常声明

上面我们讲过了异常的分类,包含了编译时异常和运行时异常。但是在Java中异常是需要声明的,当我们使用 throw 进行主动抛出异常时,需要在方法的后面加上 throws 关键字和异常的名字进行声明,否则代码无法正常编译。

public void  getName() throws CustomException1,CustomException2 .... {  //方法体 }

在这种情况下,如果别人调用我们的代码或者是我们调用其他人有类似声明的代码(例如:SimpleDateFormat 的 Parse方法)时,调用者就要对其作出反应,处理或是在调用者的方法体上继续声明,从而告诉上一层调动栈去处理,如果所有的调用栈均不处理,那么最后只能由JVM进行兜底。对于使用throws关键字进行声明的异常均为编译时异常,运行时异常在编译时无法感知,所以不需要进行异常声明。另在异常声明的时,声明的异常类型可以是抛出异常的名字或者是该异常父类的名字。

public void getName() throws Exception{
throw new CustomException1("自定义Exception异常");
}

异常的捕获

当调用异常声明的方法时,需要对其作出反应,Java提供了 try .... catch ....finally 关键字,try 中的代码块主要是用于作为异常检测,catch 用于捕获检测到的异常并处理,而 finally 则是必须执行的代码块。下面我看看一个例子

// 方法的声明
public void getName() throws CustomException { // 方法体 } // 调用体
try { getName(); }
catch(CustomException ex){ // 处理异常 }
finally{ // 必须执行的代码 }

代码 finally 体内的代码块,不管异常能不能被捕获到,都是会执行的,通常用于做资源的释放操作。上述的代码只是一个简单捕获的例子,如果 getName 方法抛出多个异常 throws CustomException1, CusomException2 , Exception ,那又该如果捕获呢?在Java中是支持多个catch 捕获异常的,当异常的种类是同级时,多 catch 的编写顺序可以使任意的,但如果异常的声明中包含非同级时( 例如包含其父类异常 ) 编写多 catch 异常捕获的时候,需要在最后写父类捕获代码。

try { getName(); }
catch(CustomException2 ex){ // 处理异常 }
catch(CustomException1 ex){ // 处理异常 }
catch(Exception ex){ // 处理异常 }
finally{ //必须执行的代码 }

方法重写时的异常处理

由于Java的编译时异常需要进行声明,Java又是面向对象编程语言,存在继承和多态特性,随之而来的就会产生对存在这种关系的方法体异常的声明该如何定义?下面我们直接来说结论

  1. 当父类中对方法进行异常声明,那么子类对该方法进行覆盖时,可以进行声明也可以不进行声明,当进行声明的时候,声明的异常在继承关系上只能是该异常或者是它的子类。
  2. 当父类中对方法没有进行异常声明时,那么子类对该方法进行覆盖时,也不可以进行异常声明,如果子类中的方法调用了带有异常声明的方法,由于这个限制,只能在方法中进行 try....catch 处理

下面我们一起看下几个场景:

父类中的方法声明异常

public class Demo {
public static void main(String[] args) throws CustomException {
Person p = new Student();
p.GetName();
}
} class Person{
public String GetName() throws CustomException { throw new CustomException("自定义异常"); }
} class Student extends Person {
public String GetName() throws CustomException2 , CustomException
{
if(true) { throw new CustomException("自定义异常"); }
else { throw new CustomException2("自定义异常2"); }
}
} class CustomException extends Exception {
public CustomException() {} public CustomException(String message) { super(message); }
} class CustomException2 extends CustomException {
public CustomException2() {} public CustomException2(String message) { super(message); }
}

class Student extends Person {
public String GetName() { // 方法体 }
}

父类中的方法未声明异常

class Person{
public String GetName() { // 方法体 }
} class Student extends Person {
public String GetName() {
try { // 调用带有异常声明的方法 }
catch( ... ) { // 处理异常 }
}
}

我们来理解一下为什么会有这样的限制?其根源即使多态性,编译看父类,运行是子类,当代码编译的时候,编译器解析的是父类的方法,查看的是父类的异常声明。如果子类中的异常声明高于父类或者和父类同级,试想如果父类是CustomException,子类的声明是 Exception,那么在编译的时候,编译器会提示需要处理异常 CustomException,但是在运行的时候,抛出的确是Exception,这样对于异常的捕捉就能造成很大的困扰,以至于达不到我们的预期。

总结

在本节中我们讲了Java中的异常,包含异常的分类,自定义异常,异常声明和捕捉以及在多态调用中异常的声明。在代码开发的过程中,我们应该在不同的场景中选择不同的异常使用。但是总体来看我们会使用运行时类型的异常会比较多,因为交付的软件预期内的问题我已经解决了,在软件运行的过程中产生的异常往往不在预期内,而且一旦发生就需要我们调整代码。

Java中异常关键字throw和throws使用方式的理解的更多相关文章

  1. Java中 try--catch-- finally、throw、throws 的用法

    一.try {..} catch {..}finally {..}用法 try { 执行的代码,其中可能有异常.一旦发现异常,则立即跳到catch执行.否则不会执行catch里面的内容 } catch ...

  2. java中异常的抛出:throw throws

    java中异常的抛出:throw throws Java中的异常抛出 语法: public class ExceptionTest{ public void 方法名(参数列表) throws 异常列表 ...

  3. java异常和throw和throws的区别

    之前在编程中编译完成后,运行时,会遇见一些常见的错误,如NullPointerException,ArrayIndexOutOfBoundsException等等 在今天重新回顾学习了java异常,总 ...

  4. 浅谈java中异常抛出后代码是否会继续执行

    问题 今天遇到一个问题,在下面的代码中,当抛出运行时异常后,后面的代码还会执行吗,是否需要在异常后面加上return语句呢? public void add(int index, E element) ...

  5. java中异常以及处理异常

    一.异常简介 什么是异常? 异常就是有异于常态,和正常情况不一样,有错误出错.在java中,阻止当前方法或作用域的情况,称之为异常. java中异常的体系是怎么样的呢? 1.Java中的所有不正常类都 ...

  6. Java 中的关键字

    Java 中有多少个关键字,有大小写之分吗? Java 中有 48 个关键字在使用 + 两个保留关键字未使用,共 50 个关键字. Java 关键字全部都由是小写组成. Java 中保留关键字分别是哪 ...

  7. Java中的关键字有哪些?「Java中53个关键字的意义及使用方法」

    Java中的关键字有哪些? 1)48个关键字:abstract.assert.boolean.break.byte.case.catch.char.class.continue.default.do. ...

  8. Java中的关键字 transient

    先解释下Java中的对象序列化 在讨论transient之前,有必要先搞清楚Java中序列化的含义: Java中对象的序列化指的是将对象转换成以字节序列的形式来表示,这些字节序列包含了对象的数据和信息 ...

  9. 《java中异常和错误》

    异常和错误的区别. 异常: 在Java中程序的错误主要是语法错误和语义错误,一个程序在编译和运行时出现的错误我们统一称之为异常,它是VM(虚拟机)通知你的一种方式,通过这种方式,VM让你知道,你(开发 ...

随机推荐

  1. delphi self.Update 什么作用

    更新指定窗口的客户区.如果窗口更新的区域不为空,UpdateWindow函数就发送一个WM_PAINT消息来更新指定窗口的客户区.函数绕过应用程序的消息队列,直接发送WM_PAINT消息给指定窗口的窗 ...

  2. IE浏览器提示打印控件未安装的一些原因

    打印控件未安装!点击这里执行安装,安装后请刷新页面或重新进入.--该提示是写在LodopFuncs.js里的.相关本博客其他博文:提示“Web打印服务CLodop未安装启动”的各种原因和解决方法.C- ...

  3. 【Leetcode_easy】994. Rotting Oranges

    problem 994. Rotting Oranges 参考 1. Leetcode_easy_994. Rotting Oranges; 完

  4. app--Android 稳定性测试方案

    标准的崩溃日志:Android 应用一般使用 Java 语言开发,在不作特殊处理的情况下,遇到未处理的异常时,会弹框提示“程序遇到异常,即将退出”(有些手机框中提示语不同, 或不弹框).同时会将异常的 ...

  5. bootstrap-table中使用bootstrap-switch开关按钮

    先上图 准备工作: 添加css和js文件 #bootstrap开关按钮#} <link href="https://cdn.bootcss.com/bootstrap-switch/3 ...

  6. AWS 数据库(七)

    数据库概念 关系型数据库 关系数据库提供了一个通用接口,使用户可以使用使用 编写的命令或查询从数据库读取和写入数据. 关系数据库由一个或多个表格组成,表格由与电子表格相似的列和行组成. 以行列形式存储 ...

  7. 查询SQL时间段内执行过的哪些SQL语句

    QS.creation_time, ) , (( ) ) AS statement_text, ST.text, QS.total_worker_time, QS.last_worker_time, ...

  8. python实践项目二:列表转字符串

    将列表各元素转换为字符串并以规定形式返回. 假定有下面这样的列表:spam = ['apples', 'bananas', 'tofu', 'cats'],将其转换成字符串:'apples, bana ...

  9. Windows 下配置 ApacheBench (AB) 压力测试

    下载 http://httpd.apache.org/download.cgi 我用的是ApacheHaus. 安装服务 1. 打开apache目录下的 conf/httpd.conf,搜索并修改 L ...

  10. 稀疏数组(java实现)

    1.稀疏数组 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组. 稀疏数组的处理方法是: 1.1记录数组一共有几行几列,有多少个不同的值 1.2把具有不同值的元素的行列 ...