当当当当当当,各位看官,好久不见,甚是想念。

  今天我们来聊聊Java里的一个小妖精,那就是异常。

什么是异常?什么是异常处理?

  异常嘛,顾名思义就是不正常,(逃),是Java程序运行时,发生的预料之外的事情,它阻止了程序按照程序员的预期正常执行。

  异常处理,应该说异常处理机制,就是专门用来制服这个小妖精的法宝。Java中的异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰。

  简而言之,Java异常处理就是能让我们主动迎击可能到来的异常,并将它们以圆润的方式处理掉。

  还是先来看个小栗子,看看java里的异常长什么样。

public class Test {
public static void main(String args[]){
int i = 0 / 0;
System.out.println("i = " + i);
}
}

  

  别慌别慌,不要看到红色提示就内心崩溃只想关掉IDE,来,抓紧我的手,带你看清“异常”这个磨人的小妖精的真面目(滑稽)。

  代码里将0作为了分母,因此程序会发生算术异常,抛出一个异常后,如果没有任何处理,默认会终止程序,所以后面的打印内容并没有输出。在异常内容里,有说明异常类型为:java.lang.ArithmeticException,也就是算术异常,后面跟着的是异常原因: / by zero,也就是说异常出现的原因是将0作为了分母,而且后面还有堆栈信息,指出了异常抛出的位置是在com.frank.chapter16.main.Test.main这个包下,Test类的第11行(这个行数如果跟你想的不一样,不要在意,因为我的代码开始之前还有一些不可描述的说明信息),因为只有一次方法调用,所以没有很长的堆栈信息,看起来也很简洁明了。

  所以你看,其实异常也没那么可怕吧,不仅给了异常原因,还告诉了你这个bug是出在第几行,所以好好利用它,可以帮助你写出更难以发现的bug,呸,说错了,可以帮助你更容易找到bug(手动滑稽)。

  如果不希望抛出异常后程序就结束,而是希望它继续运行呢?那么就捕获它。

如何使用异常处理

  我们来把上面那个栗子改改:

public class Test {
public static void main(String args[]){
try{
int i = 0 / 0;
}catch (Exception e){
System.out.println("好像发生异常了,但是我不管,我还要继续运行");
}
System.out.println("运行完毕!");
}
}

  输出如下:

好像发生异常了,但是我不管,我还要继续运行
运行完毕!

  好的,很强势,现在即使抛出了异常,程序也继续运行了。异常就像是一头野兽,但你一旦捕获它,驯服它,就可以为你所用,为所欲为了。

  try...catch...是常用的异常处理搭配,如果在try语句块中发生了异常,如果刚好这个异常被捕获到了,那么会直接跳到catch语句块中,执行catch语句中的代码,像上面的栗子里,因为对Exception类进行了捕获处理,所以当它的子类异常java.lang.ArithmeticException被抛出来的时候,也能捕获它。关于Exception类的结构层次关系,后面再做详细介绍。

  还有另外一种搭配方式,那就是try...catch...finally,finally语句块比catch要强势的多,前面说了catch语句块必须要捕获到了特定的Exception才会执行里面的代码,如果catch的是ArithmeticException但是抛出的却是空指针异常,那就不会被捕获了,异常也就逃之夭夭了。这个时候,finally的优势就展示出来了,不管抛出什么样的异常,也不管是否抛出了异常,finally中的代码都会被执行。所以一般的用法是在finally语句块里释放掉那些需要被释放的资源,如socket连接,关闭io流,关闭数据库连接等等。也就是说一般在finally中收拾try中抛出的烂摊子,心疼一秒finally,果然能者多劳啊。

  当然,try...finally这样的搭配也是ok的,需要注意的是,当try语句中发生了异常之后,在发生异常处之后的代码将不会再执行,而是跳到相应的catchu或者finally中去。

public class Test {
public static void main(String args[]){
try{
int i = 0 / 0;
}catch (NullPointerException e) {
System.out.println("这里捕获空指针异常");
}catch (ArithmeticException e){
System.out.println("这里捕获算术异常");
}finally {
System.out.println("这里是finally");
}
System.out.println("运行完毕!");
}
}

  输出如下:

这里捕获算术异常
这里是finally
运行完毕!

  在上面的代码中,catch语句块是可以同时使用多个的,第一个catch语句块捕获的是空指针异常,但由于抛出的是算术异常,所以没有捕获住,但被第二个catch捕获到了,所以第二个catch语句块中的代码执行了。异常匹配是按照从上到下的顺序进行匹配的,最后才执行finally中的代码块。关于try...catch...finally,还有一个很有趣的return问题,如果三个语句块里都有return,最终返回结果会是怎样呢?这里做了详细的说明,http://www.cnblogs.com/mfrank/p/7895660.html 有兴趣的话可以看一看。

  绝大多数情况下,finally中的代码都是会被执行的,只有一种情况下,finally中的代码不会被执行,那就是在try语句块中结束掉了虚拟机(如:使用 System.exit(0); )。

  关于异常,还有一个关键字需要介绍,那就是throw,使用throw可以主动抛出一个异常。看到这你也许会一脸懵逼,主动抛出???嫌异常不够多,凑热闹不嫌事大??别急别急,中间一定有什么误会,把刀放下,有话好好说。

  throw关键字确实是用来抛出异常的,你可以这样使用:

public class Test {
public static void main(String args[]){
try{
throw new NullPointerException("听说你很闲,给你抛个异常。");
}catch (NullPointerException e) {
System.out.println("这里捕获空指针异常,提示内容:" + e.getMessage());
e.printStackTrace();
}
}
}

  输出如下:

这里捕获空指针异常,提示内容:听说你很闲,给你抛个异常。
java.lang.NullPointerException: 听说你很闲,给你抛个异常。
at com.frank.chapter16.main.Test.main(Test.java:11)

  用throw关键字可以抛出任意类型的异常,当然,你想的话,还有抛Error,至于什么是Error,已经跟Exception的关系,将在下一篇里进行讲解。暂时不用深究。

  在throw异常的时候,可以加上抛出异常的原因,这样可以更方便定位问题所在,当然,一般来说不会像栗子中这样使用的,这里只是为了简单起见。

  到此为止,异常的上半篇已经讲解完毕,在这一篇里,说明了什么是异常,什么是异常处理,以及如何使用异常处理机制。相信大家对这个小妖精有了初步的认识,下一篇中,将会讲解Exception家族都有哪些成员,如何使用自定义异常,已经异常处理的实际使用中的正确姿势。欢迎大家继续关注,之后计划每周两篇以上的更新,如果有讲解遗漏或者不好的地方,欢迎大家及时指出,共同进步!

【Java入门提高篇】Day16 Java异常处理(上)的更多相关文章

  1. 【Java入门提高篇】Day25 史上最详细的HashMap红黑树解析

    当当当当当当当,好久不见,最近又是换工作,又是换房子,忙的不可开交,断更了一小段时间,最重要的一篇迟迟出不来,每次都犹抱琵琶半遮面,想要把它用通俗易懂的方式进行说明,确实有一定的难度,可愁煞我也,但自 ...

  2. 【Java入门提高篇】Java集合类详解(一)

    今天来看看Java里的一个大家伙,那就是集合. 集合嘛,就跟它的名字那样,是一群人多势众的家伙,如果你学过高数,没错,就跟里面说的集合是一个概念,就是一堆对象的集合体.集合就是用来存放和管理其他类对象 ...

  3. 【Java入门提高篇】Day16 Java异常处理(下)

    今天继续讲解java中的异常处理机制,主要介绍Exception家族的主要成员,自定义异常,以及异常处理的正确姿势. Exception家族 一图胜千言,先来看一张图. Exception这是一个父类 ...

  4. 【Java入门提高篇】Day1 抽象类

    基础部分内容差不多讲解完了,今天开始进入Java提高篇部分,这部分内容会比之前的内容复杂很多,希望大家做好心理准备,看不懂的部分可以多看两遍,仍不理解的部分那一定是我讲的不够生动,记得留言提醒我. 好 ...

  5. 【Java入门提高篇】Day21 Java容器类详解(四)ArrayList源码分析

    今天要介绍的是List接口中最常用的实现类——ArrayList,本篇的源码分析基于JDK8,如果有不一致的地方,可先切换到JDK8后再进行操作. 本篇的内容主要包括这几块: 1.源码结构介绍 2.源 ...

  6. 【Java入门提高篇】Day13 Java中的反射机制

    前一段时间一直忙,所以没什么时间写博客,拖了这么久,也该更新更新了.最近看到各种知识付费的推出,感觉是好事,也是坏事,好事是对知识沉淀的认可与推动,坏事是感觉很多人忙于把自己的知识变现,相对的在沉淀上 ...

  7. 【Java入门提高篇】Day31 Java容器类详解(十三)TreeSet详解

    上一篇很水的介绍完了TreeMap,这一篇来看看更水的TreeSet. 本文将从以下几个角度进行展开: 1.TreeSet简介和使用栗子 2.TreeSet源码分析 本篇大约需食用10分钟,各位看官请 ...

  8. 【Java入门提高篇】Day28 Java容器类详解(十)LinkedHashMap详解

    今天来介绍一下容器类中的另一个哈希表———>LinkedHashMap.这是HashMap的关门弟子,直接继承了HashMap的衣钵,所以拥有HashMap的全部特性,并青出于蓝而胜于蓝,有着一 ...

  9. 【Java入门提高篇】Day27 Java容器类详解(九)LinkedList详解

    这次介绍一下List接口的另一个践行者——LinkedList,这是一位集诸多技能于一身的List接口践行者,可谓十八般武艺,样样精通,栈.队列.双端队列.链表.双向链表都可以用它来模拟,话不多说,赶 ...

  10. 【Java入门提高篇】Day26 Java容器类详解(八)HashSet源码分析

    前面花了好几篇的篇幅把HashMap里里外外说了个遍,大家可能对于源码分析篇已经讳莫如深了.别慌别慌,这一篇来说说集合框架里最偷懒的一个家伙——HashSet,为什么说它是最偷懒的呢,先留个悬念,看完 ...

随机推荐

  1. 《java入门第一季》之Socket编程通信和TCP协议通信图解

    Socket编程通信图解原理: TCP协议通信图解

  2. java Domj4读取xml文件

    先概括,再以代码形式给出. 获取节点: Iterator  Element.nodeIterator();  //获取当前标签节点下的所有子节点 获取 标签: Element Document.get ...

  3. Linux 句柄是什么 ?

    1.句柄就是一个标识符,只要获得对象的句柄,我们就可以对对象进行任意的操作. 2.句柄不是指针,操作系统用句柄可以找到一块内存,这个句柄可能是标识符,map的key,也可能是指针,看操作系统怎么处理的 ...

  4. H5学习之旅-H5的格式化(4)

    H5的格式设置: b代表是粗体 i斜体 big 字体变大 small变小 em强调 strong 加强和变粗差不多 sub 定义下标字 sup 定义上标字 ins 插入字 del 删除字 代码实例 & ...

  5. Java进阶(二十)解疑答惑之何时字符串才算真正为空?

    解疑答惑之何时字符串才算真正为空? 在一次编码过程中,有一个现象一直困扰着自己,经过后台的不断调试,才发现原来有时候字符串的空非空.测试代码如下: // medname可为药品名称或药品ID Stri ...

  6. Android百分比布局支持库(android-percent-support)

    Android中提供了五种布局,其中用的最多的就是:LinearLayout, RelativeLayout 和 FrameLayout这三种布局,在对某一界面进行布局时最先想到也是通过这三种来布局的 ...

  7. Android进阶(十九)AndroidAPP开发问题汇总(三)

    Android进阶(十九)AndroidAPP开发问题汇总(三) Java解析XML的几种方式: http://inotgaoshou.iteye.com/blog/1012188 从线程返回数据的两 ...

  8. Android虚拟设备访问WebSocket问题

    Android虚拟设备访问WebSocket问题 最近写erlang的WebSocket网站,需要运行在RHEL6上,用Android设备访问. 可惜AVD无法访问主机 Win7上的虚拟机(RHEL6 ...

  9. ROS探索总结(十四)——move_base(路径规划)

    在上一篇的博客中,我们一起学习了ROS定位于导航的总体框架,这一篇我们主要研究其中最重要的move_base包. 在总体框架图中可以看到,move_base提供了ROS导航的配置.运行.交互接口,它主 ...

  10. 【52】java多线程剖析

    线程的状态: 线程共有下面4种状态: 新建状态(New): 新创建了一个线程对象,当你用new创建一个线程时,该线程尚未运行. 就绪状态(Runnable): 线程对象创建后,其他线程调用了该对象的s ...