前段时间集合的整理真的是给我搞得心力交瘁啊,现在可以整理一些稍微简单一点的,搭配学习 ~

突然想到一个问题,这些东西我之前就整理过,现在再次整理有什么区别嘛?我就自问自答一下,可能我再次整理会看到不一样的一面,会从源码和整体来看。其次,之前的整理都是在某个地方止步,可持续性较差,现在就尽力坚持住。因为还有你们再看 ~ 另外,欢迎各行各业的同学们给我投稿,让大家都能互相了解,岂不是很棒!

进入正题,看看 Java 中的异常处理。当程序执行的时候没有按照我们的意思执行,发生了一些不可言语的 bug 时,你打算怎么搞?不管不问,还是主动出击,而 Java 语言为此就准备了一套处理异常的类。

Throwable 类是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。

两个子类,Error 和 Exception,通常用于指示发生了异常情况。通常,这些实例是在异常情况的上下文中最新创建的,因此包含了相关的信息(比如堆栈跟踪数据)。Throwable 包含了其线程创建时线程执行堆栈的快照。还可以给出错误提示信息。

Error 及其子类表示的是错误,是 JVM 本身出错了,不能由程序控制,我们最主要就是看异常。

Exception 及其子类表示的是异常,异常又分为检查异常和非检查异常,这是在 javac 编译器的角度进行分类的,检查异常在我们编写代码的时候会提示出来,我们必须要对其进行处理,处理方式有两种,下面看。非检查时异常对应于上图中的 RuntimeException ,编译的时候不报错,在运行的时候才会出现。

在 Java 中处理异常有两种思路,自己解决掉,干净利索或是抛给方法的调用者,就像你有事会找警察一样,当然警察不一定能给你解决,就像是你抛出的异常可能会被再次抛出去一样。最终会抛给 JVM ,然后程序挂掉。

自己处理主要是使用 try { } catch ( ) { } finally { } 语句块,使用 try 包裹可能出现异常的代码,使用 catch 来捕获可能出现的异常。最后 finally 语句块是用来执行那些必须要执行的代码,比方说释放资源文件,关闭数据库连接等操作。

有几点需要说明一下:

1 可以有多个 catch 语句块,但是捕获异常的顺序一定要注意,当异常出现时,只要被 catch 捕获,则下面的 catch 不再执行。所以我们要把范围小的异常种类或者说子类放在上面。

2 我们都听过 finally 语句块是一定会执行的,其实不是这样的,当遇到 system.exit() 就不会再执行了,因为你强制退出 JVM 了。除此之外,确实是一定执行的。

3 只有 catch 块才能处理异常,try 只是圈起范围的作用,而 finally 块是善后作用。

4 try catch finally 语句块中的变量都是局部变量,它们之间是不能共享的,待会看个例子。

另一种方式就是自己搞不定就使用 throws 抛出去,抛给方法的调用者,让它们去处理。在方法的声明中添加语句 throws ,即可将检查时异常抛出,后续的处理就留给方法的 caller 吧!

上面都是在检查异常发生时我们可以做的相应处理,若是运行时发生了异常,还有一种操作可以在代码执行的过程中手动的抛出一个异常,使用 throw 关键字,例如这样:

String name;
if(name == "null"){
throw new IllegalArgumentException("姓名不能为空");
}

因为异常的产生是会形成连锁反应,一旦有异常发生,所有的调用者都会发生异常,异常发生最开始的地方就是异常的抛出点,抛出点的异常会向 caller 转移。所以在方法的重写中,子类抛出的异常类型一定要小于或等于父类的抛出异常类型,不然,你想想,子类 throws 出去的异常太大,父类肯定接不住呀。

最后就是要看一个例子,来看一下 return 语句在语句块中的应用。加深一下对异常处理的理解。

class Test {
public int aaa() {
int x = 1; try {
return ++x;
} catch (Exception e) { } finally {
++x;
}
return x;
} public static void main(String[] args) {
Test t = new Test();
int y = t.aaa();
System.out.println(y);
}
}

问:最后打印 y 是多少 ? 执行的过程是怎么的 ?

结果是 2 ,过程却可能不是那么好解释,在 try 语句中我们执行 ++x 然后就直接返回 2 ? 肯定不是,因为还要执行 finally 语句块啊,所以 Java 规范规定,在存在 finally 块时,会将 try 中的 return 放在一边,而优先执行 finally 中的代码,但是已经得到的结果 2 可没有丢了,而是存在了 try 块中的本地变量表中,以备不时之需。

在执行 finally 块之后,x 等于 3 ,一样的还是会将 3 保存在 finally 块的本地变量表中,然后再回到 try 中进行 return 操作,此时,方法结束,返回的结果就是之前保存在 try 块本地变量表中的 2 。假如我们在 finally 块中也有 return 语句,就会返回 3 而不再执行 try 中的 return 语句,然而 Java 规范不希望我们这么做,因为 finally 语句块的主要作用是为了释放资源,关闭连接操作。

结合这个例子我们要明白,在每个语句块中都会存在一个本地表量表,会保存使用到变量的值,各个语句块是分离开的,所以在执行 return 语句的时候,返回的是本地变量表中的变量。

在 finally 块中使用 return 还有一个弊端,它会抑制 try 和 catch 中的异常的抛出。看下面例子,在 try 块中也是一样的。

public static void main(String[] args) {
int result;
try{
result = foo();
System.out.println(result); //输出100
} catch (Exception e){
System.out.println(e.getMessage()); //没有捕获到异常
}
//catch中的异常被抑制
@SuppressWarnings("finally")
public static int foo() throws Exception {
try {
int a = 5/0;
return 1;
}catch(ArithmeticException amExp) {
throw new Exception("我将被忽略,因为下面的finally中使用了return");
}finally {
return 100;
}
} //try中的异常被抑制
@SuppressWarnings("finally")
public static int bar() throws Exception {
try {
int a = 5/0;
return 1;
}finally {
return 100;
}
}

总结

return 语句代表方法结束,但是遇到 finally 语句块也是要等一等的。

无论 try 里执行了 return 语句、break 语句、还是 continue 语句,finally 语句块还会继续执行,除非遇上了 system.exit() 。

finally 中不建议使用 return 语句的,释放资源就好。

推荐阅读:

Java 集合之 Map

Java 集合之 Collection

String 的常用操作

Sting 与不可变对象

Java 中的异常的更多相关文章

  1. 【Java心得总结二】浅谈Java中的异常

    作为一个面向对象编程的程序员对于 下面的一句一定非常熟悉: try { // 代码块 } catch(Exception e) { // 异常处理 } finally { // 清理工作 } 就是面向 ...

  2. Java中的异常-Throwable-Error-Exception-RuntimeExcetpion-throw-throws-try catch

    今天在做一个将String转换为Integer的功能时,发现Integer.parseInte()会抛出异常NumberFormatException. 函数Integer.parseInt(Stri ...

  3. Java中的异常详解

    一.异常定义 阻止当前方法或作用域继续执行的问题,称为异常 二.异常分析      所有不正常类都继承Throwable类,这个类主要有两个子类Error类和Exception类.Error指系统错误 ...

  4. Java中的异常和处理详解

    简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言风格:用函数返回值作为执行状态?. ...

  5. Java中的异常简介

    Java中异常的分类 Java中的异常机制是针对正常运行程序的一个必要补充,一般来说没有加入异常机制,程序也能正常运营,但是,由于入参.程序逻辑的严谨度,总会有期望之外的结果生成,因此加入异常机制的补 ...

  6. java中的异常类

    Java中的异常: 1. Throwable是所有异常的根,java.lang.Throwable Throwable包含了错误(Error)和异常(Exception),Exception又包含了运 ...

  7. Java 中的异常和处理详解

    Java 中的异常和处理详解 原文出处: 代码钢琴家 简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误 ...

  8. Java 中的异常和处理详解(转载)

    原文出处: 代码钢琴家 简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言风格:用函 ...

  9. Java中的异常和处理详解(转发:https://www.cnblogs.com/lulipro/p/7504267.html)

    简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言风格:用函数返回值作为执行状态?. ...

随机推荐

  1. 环境变量ANDROID_SDK_HOME的作用

    默认情况下,开发者创建的AVD(Android Virtual Device)存放在家目录的.android下. 如果是Linux,其路径就是 /home/<your_user_name> ...

  2. debian旧日笔记

    18:45 2007-10-7 序 图形界面较好的Linux操作系统有三个主要的发行版本:RedHat, Debian, SuSE.自RedHat9后,RedHat以Fedora为名发行新的版本.仍然 ...

  3. LintCode 388: Kth Permutation

    LintCode 388: Kth Permutation 题目描述 给定 n 和 k,求123..n组成的排列中的第 k 个排列. 样例 对于 n = 3, 所有的排列如下: 123 132 213 ...

  4. backup服务器之rsync服务

    backup服务器之rsync服务   rsync是开源的.快速的.多功能的可实现全量及增量的本地或远程数据同步备份的优秀工具.它拥有scp.cp的全量复制功能,同时比scp.cp命令更优秀.更强大. ...

  5. Node程序debug小记

    有时候,所见并不是所得,有些包,你需要去翻他的源码才知道为什么会这样. 背景 今天调试一个程序,用到了一个很久之前的NPM包,名为formstream,用来将form表单数据转换为流的形式进行接口调用 ...

  6. Chrome 清除某个特定网站下的缓存

    打开开发者工具(F12),选择 Network--Disable cache 即可.需要清除某网站缓存时 F12 打开开发者工具就会自动清除这个网站的缓存,而不必清除所有网站的缓存了.

  7. imperva 非交互式导入导出配置

    非交互使用模式full_expimp.sh可以导出/导入手动使用交互式CLI 在root的命令行下执行: 例子:导出:# full_expimp.sh --operation=1 --pwd=密码 - ...

  8. 遍历 USB devcie,读取设备描述符 device descriptor【转】

    转自:http://blog.csdn.net/flyyyri/article/details/5480347 理论:    对于USB接口的设备,现在越来越多了.本篇我们就通过获取一个USB扫描仪设 ...

  9. select()函数用法一

    select()函数用法以及FD_ZERO.FD_SET.FD_CLR.FD_ISSET select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用 ...

  10. HDU 6215 2017Brute Force Sorting 青岛网络赛 队列加链表模拟

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6215 题意:给你长度为n的数组,定义已经排列过的串为:相邻两项a[i],a[i+1],满足a[i]&l ...