异常的捕获及处理

异常:异常是指中断程序正常执行的一种指令流

 在JAVA程序中一旦出现了异常,而程序又没有及时处理的情况下,那么程序会中断执行。

例如,观察以下的代码:

public class Demo22{

 public static void main(String args[]){

 int i = 10 ;

 int j = 0 ;

 System.out.println(" --------- 计算开始 ---------") ;

 System.out.println("i / j = " + (i / j)) ; à 此段代码出现了异常

 System.out.println(" --------- 计算结束 ---------") ;

 }

};

 以上代码编译的时候不存在任何的问题,那么执行时,出错了,打印内容如下:

--------- 计算开始 ---------

Exception in thread "main" java.lang.ArithmeticException: / by zero

 at Demo22.main(Demo22.java:6)

 整个程序,在出现异常的代码之后不再被执行了,异常之前的程序呢?正确的执行了。

 那么在JAVA中我们所处理的异常都属于运行时异常,即:执行JAVA程序的时候出现的错误,那么实际上对于JAVA的异常分类应该按如下的形式划分:

 ArithmeticException à RuntimeException à Exception(往往是要由用户自己处理的)

 所以对于异常而言,它是一个统称,代表了:

 Throwable(可能的抛出)

|- Exception:表示需要人为处理的异常,指的是程序的错误 à 因为程序的错误较多,所以就习惯了把所有的错误都统一成为异常。

 |- Error:表示JVM错误,人为不能处理

异常的处理格式如下:

try{

 包含可能出现错误的代码段 ;

}catch(出错的类型 出错的对象){

 对于错误的处理语句 ;

}

 那么使用如上的格式修改之前的代码,保证程序可以正确的执行完:

public class Demo23{

 public static void main(String args[]){

 int i = 10 ;

 int j = 0 ;

 System.out.println(" --------- 计算开始 ---------") ;

 try{

 System.out.println("i / j = " + (i / j)) ;

 }catch(ArithmeticException e){

 System.out.println("计算出现了错误。。。") ;

 }

 System.out.println(" --------- 计算结束 ---------") ;

 }

};

 但是以上的程序依然存在了些小小的问题,例如:对于计算,往往应该由用户自己输入数据,所以此时可以通过接收参数为其输入数据。代码如下:

public class Demo24{

 public static void main(String args[]){

 int i = 10 ;

 int j = 0 ;

 System.out.println(" --------- 计算开始 ---------") ;

 try{

 i = Integer.parseInt(args[0]) ;

 j = Integer.parseInt(args[1]) ;

 System.out.println("i / j = " + (i / j)) ;

 }catch(ArithmeticException e){

 System.out.println("计算出现了错误。。。") ;

 }

 System.out.println(" --------- 计算结束 ---------") ;

 }

};

 如果现在输入的内容是正确的数字,则程序不会有任何的问题,但是既然数据是由用户自己输入的,那么肯定会输入各种违法的数据。

 存在的问题:

 · 不输入任何参数,出现数组越界:ArrayIndexOutOfBoundsException

 · 输入的参数不是数字,出现了数字格式转换错误:NumberFormatException

 · 输入的被除数是0,出现算术错误:ArithmeticException

 在以上的错误之中,只有算术错误被处理了,因为在程序上具备了算术错误的处理能力。那么也就意味着,现在的异常处理并不完善,需要加入更多的处理,所以需要编写更多的catch。

 以上的程序修改为:

public class Demo24{

 public static void main(String args[]){

 int i = 10 ;

 int j = 0 ;

 System.out.println(" --------- 计算开始 ---------") ;

 try{

 i = Integer.parseInt(args[0]) ;

 j = Integer.parseInt(args[1]) ;

 System.out.println("i / j = " + (i / j)) ;

 }catch(ArithmeticException e){

 System.out.println("算术错误。。。"+e) ;

 }

 catch(ArrayIndexOutOfBoundsException e){

 System.out.println("没有输入参数。。。"+e) ;

 }

 catch(NumberFormatException e){

 System.out.println("输入的内容不是数字。。。"+e) ;

 }

 System.out.println(" --------- 计算结束 ---------") ;

 }

};

 但是会发现比较麻烦,因为现在已经知道了的是三个错误,那么对于很多未知道的错误呢?那么此时,就需要分析异常的产生过程。

 发现catch中接收的内容都是对象,那么也就意味着,所谓的异常,就是自动产生了一个异常类的实例化对象。一出错就产生。

 对象有一个特点,可以向上自动转型,Exception是用户需要处理的最大异常,那么证明所有的对象都可以向Exception转换。

public class Demo25{

 public static void main(String args[]){

 int i = 10 ;

 int j = 0 ;

 System.out.println(" --------- 计算开始 ---------") ;

 try{

 i = Integer.parseInt(args[0]) ;

 j = Integer.parseInt(args[1]) ;

 System.out.println("i / j = " + (i / j)) ;

 }catch(ArithmeticException e){

 System.out.println("算术错误。。。"+e) ;

 }

 catch(ArrayIndexOutOfBoundsException e){

 System.out.println("没有输入参数。。。"+e) ;

 }

 catch(NumberFormatException e){

 System.out.println("输入的内容不是数字。。。"+e) ;

 }

 catch(Exception e){

 System.out.println("其他异常。。。"+e) ;

 }

 System.out.println(" --------- 计算结束 ---------") ;

 }

};

注意:

 如果在程序中出现了多个catch语句,则捕获更粗的catch要放在捕获更细的catch之后。

public class Demo25{

 public static void main(String args[]){

 int i = 10 ;

 int j = 0 ;

 System.out.println(" --------- 计算开始 ---------") ;

 try{

 i = Integer.parseInt(args[0]) ;

 j = Integer.parseInt(args[1]) ;

 System.out.println("i / j = " + (i / j)) ;

 }catch(Exception e){

 System.out.println("其他异常。。。"+e) ;

 }catch(ArithmeticException e){

 System.out.println("算术错误。。。"+e) ;

 }catch(ArrayIndexOutOfBoundsException e){

 System.out.println("没有输入参数。。。"+e) ;

 }catch(NumberFormatException e){

 System.out.println("输入的内容不是数字。。。"+e) ;

 }

 System.out.println(" --------- 计算结束 ---------") ;

 }

};

 则编译的时候出现了以下的错误,说是许多的异常已经被捕获了。

Demo25.java:14: 已捕捉到异常 java.lang.ArithmeticException

 catch(ArithmeticException e){

 ^

Demo25.java:17: 已捕捉到异常 java.lang.ArrayIndexOutOfBoundsException

 catch(ArrayIndexOutOfBoundsException e){

 ^

Demo25.java:20: 已捕捉到异常 java.lang.NumberFormatException

 catch(NumberFormatException e){

 ^

3 错误

 既然所有异常类的对象都可以向Exception转换,那么是不是直接使用Exception接收更方便?

public class Demo26{

 public static void main(String args[]){

 int i = 10 ;

 int j = 0 ;

 System.out.println(" --------- 计算开始 ---------") ;

 try{

 i = Integer.parseInt(args[0]) ;

 j = Integer.parseInt(args[1]) ;

 System.out.println("i / j = " + (i / j)) ;

 System.out.println("***************************") ;

 }catch(Exception e){

 System.out.println(e) ;

 }

 System.out.println(" --------- 计算结束 ---------") ;

 }

};

 以上是异常处理的一种格式,实际上异常处理还有另外一种格式,就是说,可以为异常做一个统一的出口,不管是否发生了异常,都要执行此代码:

try{

 包含可能出现错误的代码段 ;

}catch(出错的类型 出错的对象){

 对于错误的处理语句 ;

}finally{

 不管是否出现异常,都执行此代码 ;

}

 代码如下:

public class Demo27{

 public static void main(String args[]){

 int i = 10 ;

 int j = 0 ;

 System.out.println(" --------- 计算开始 ---------") ;

 try{

 i = Integer.parseInt(args[0]) ;

 j = Integer.parseInt(args[1]) ;

 System.out.println("i / j = " + (i / j)) ;

 }catch(Exception e){

 System.out.println(e) ;

 }finally{ à 典型的程序出口

 System.out.println("不管是否存在异常,此代码都会被执行。。。") ;

 }

 System.out.println(" --------- 计算结束 ---------") ;

 }

};

在异常处理中还有两个很重要的关键字

 · throws:在方法的声明处使用,表示此方法不处理异常,而交给被调用处处理。

 · throw:表示人为的抛出一个异常。

例如:定义一个数学类,里面有一个除法

class Math{

 // 此代码有可能发生问题,也有可能不发生问题

 // 一旦发生问题,找调用处,谁调用的此方法,谁去处理

 public int div(int i,int j) throws Exception{

 return i / j ;

 }

};

public class Demo28{

 public static void main(String args[]){

 Math m = new Math() ;

 System.out.println(m.div(10,2)) ;

 }

};

 按规定来说,此方法在调用的时候使用异常的捕获,如果不使用,则编译时出现以下的错误提示:

Demo28.java:11: 未报告的异常 java.lang.Exception;必须对其进行捕捉或声明以便抛出

 System.out.println(m.div(10,2)) ;

 ^

1 错误

 所以对于调用有throws声明的方法,必须使用try…catch:

class Math{

 // 此代码有可能发生问题,也有可能不发生问题

 // 一旦发生问题,找调用处,谁调用的此方法,谁去处理

 public int div(int i,int j) throws Exception{

 return i / j ;

 }

};

public class Demo28{

 public static void main(String args[]){

 Math m = new Math() ;

 try{

 System.out.println(m.div(10,0)) ;

 }catch(Exception e){

 System.out.println(e) ;

 }

 }

};

 问?既然main方法是一个方法,那么能不能在主方法上编写throws语句呢?肯定是可以的

class Math{

 // 此代码有可能发生问题,也有可能不发生问题

 // 一旦发生问题,找调用处,谁调用的此方法,谁去处理

 public int div(int i,int j) throws Exception{

 return i / j ;

 }

};

public class Demo29{

 public static void main(String args[]) throws Exception{

 Math m = new Math() ;

 System.out.println(m.div(10,0)) ;

 }

};

 观察错误的提示:

Exception in thread "main" java.lang.ArithmeticException: / by zero

 at Math.div(Demo29.java:5)

 at Demo29.main(Demo29.java:11)

 可以发现以上的错误提示与不使用try…catch效果是一样的,证明所有的错误都交给了JVM进行处理,实际上在JAVA中默认的处理方式也就是使用JVM完成。

 throw:表示在程序中人为的抛出一个异常,而且必须使用try…catch进行处理。

public class Demo30{

 public static void main(String args[]){

 try{

 throw new Exception("我自己乐意抛。。。") ;

 }catch(Exception e){

 System.out.println(e) ;

 }

 }

};

 因为对于异常而言,最终结果肯定都是抛出一个异常的实例化对象。所以是自己抛还是系统抛都肯定需要进行异常的捕获及处理。

 设计一个除法操作,在操作之前编写:计算开始,在操作之后编写计算结束,中间不管是否出现了错误,都要打印这样两句话,问:该如何实现?

class Math{

 public int div(int i,int j) throws Exception{

 System.out.println(" ======== 计算开始 =========") ;

 int temp = 0 ;

 try{

 temp = i / j ;

 }catch(Exception e){

 throw e ;

 }finally{

 System.out.println(" ======== 计算结束 =========") ;

 }

 return temp ;

 }

};

public class Demo31{

 public static void main(String artgs[]){

 Math m = new Math() ;

  try{

 System.out.println(m.div(1,0)) ;

 }catch(Exception e){

 System.out.println(e) ;

 }

 }

};

 一般而言,对于throw、throws、finally往往会一起使用。

自定义异常:

 一个类只要继承了Exception就可以称为一个异常类。

class MyException extends Exception{

 public MyException(String msg){

 super(msg) ;

 }

};

public class Demo32{

 public static void main(String args[]){

 try{

 throw new MyException("自己定义玩的。。") ;

 }catch(Exception e){

 System.out.println(e) ;

 }

 }

};

注意点:

 · throw与throws的区别?

 |- throw:是人为抛出异常

 |- throws:方法声明处使用,表示在方法中不处理异常

 · final与finally

 |- final:定义类、方法、常量

 |- finally:异常的统一出口

写在最后:

码字不易看到最后了,那就点个关注呗,只收藏不点关注的都是在耍流氓!

关注并私信我“架构”,免费送一些Java架构资料,先到先得!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,875评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,569评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,475评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,459评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,537评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,563评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,580评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,326评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,773评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,086评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,252评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,921评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,566评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,190评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,435评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,129评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,125评论 2 352

推荐阅读更多精彩内容

  • Java经典问题算法大全 /*【程序1】 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子...
    赵宇_阿特奇阅读 1,858评论 0 2
  • 【程序1】 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔...
    开心的锣鼓阅读 3,313评论 0 9
  • 50道经典Java编程练习题,将数学思维运用到编程中来。抱歉哈找不到文章的原贴了,有冒犯的麻烦知会声哈~ 1.指数...
    OSET我要编程阅读 6,960评论 0 9
  • JAVA面试题 1、作用域public,private,protected,以及不写时的区别答:区别如下:作用域 ...
    JA尐白阅读 1,150评论 1 0
  • Day01 class 例子{ public static void main(String[] args){ ...
    周书达阅读 1,027评论 0 0