Java学习21:异常

异常

什么是异常,java提供异常处理机制有什么用?
程序执行过程中发生了不正常的情况,而这种不正常的情况叫做:异常

java语言是很完善的语言,提供了异常的处理方式,程序执行过程中出现了不正常的情况,java把该异常信息打印输出到控制台,供程序员参考。程序员看到异常信息之后,可以对程序进行修改,让程序更加健壮。

程序在执行时控制台出现了异常信息。这个信息是JVM打印的。

什么是异常:程序执行过程中的不正常情况。
异常的作用:增强程序的健壮性。

java语言中异常是以什么形式存在的呢?
1、异常在java中以类的形式存在,每一个异常类都可以创建异常对象。
2、异常对应的现实生活中是怎样的?
火灾(异常类):
2008年8月8日,小明家着火了(异常对象)
2008年8月9日,小刚家着火了(异常对象)
2008年9月8日,小红家着火了(异常对象)
类是:模板。
对象是:实际存在的个体。

异常的继承结构

我们可以使用UML图来描述一下继承结构。
画UML图有很多工具,例如:Rational Rose(收费的)、starUML等......

什么是UML?有什么用?
UML是一种统一建模语言。
一种图标式语言(画图的)
UML不是只有java中使用。只要是面向对象的编程语言,都有UML。
一般画UML图的都是软件架构师或者说是系统分析师,这些级别的人员使用的。
软件设计人员使用UML。

在UML图中可以描述类与类之间的关系,程序执行的流程,对象的状态等。

在java软件开发中,软件分析师/设计师负责设计类,java软件开发人员必须要能看懂。

Object类下的Throwable类下有两个子类,Error和Exception。

所有的错误只要发生,Java程序只有一个结果那就是终止程序的执行,退出JVM,错误是不能处理的。

Exception下有两部分,一部分是Exception的直接子类,一部分是RuntimeException。

所有的Exception的直接子类,都叫做编译时异常。编译时异常是在编译阶段发生的么?不是。编译时异常是表示必须在编写程序的时候预先对这种异常进行处理,如果不处理编译器报错。编译时异常又被称为受检异常,还有叫做受控异常。

所有的RuntimeException及子类都属于运行时异常。运行时异常在编写程序阶段,你可以选择处理,也可以不处理。运行时异常还有另一些名字:未受检异常、或者非受控异常。

不管是错误,还是异常,都是可抛出的。

注意:编译时异常和运行时异常,都是发生在运行阶段。编译阶段异常是不会发生的。

编译时异常为什么而得名?
因为编译时异常必须在编写代码时预先处理,如果不处理编译器报错,因此得名。

所有异常都是在运行阶段发生的。因为只有程序运行阶段才可以new对象。
因为异常的发生就是new异常对象。

编译时异常和运行时异常的区别

编译时异常一般发生的概率比较高。
举个栗子:
你看到外面下雨了,你出门之前会预料到:如果不打伞,我可能会生病(生病是一种异常)。而且这个异常发生的概率很高,所以出门前要拿一把伞。
“拿一把伞”就是对“生病异常”发生之前的一种处理方式。

对于一些发生概率较高的异常,需要在运行之前对其进行预处理。

运行时异常一般发生的概率比较低。
举个栗子:
小明走在大街上,可鞥会被天上的飞机轮子砸到。被飞机轮子砸到也算是一种异常。但是这种异常发生的概率较低。在出门之前没必要提前对这种发生概率较低的异常进行预处理。如果预处理这种异常,你会活的很累。

假设Java中没有对异常进行划分,没有分为编译时异常和运行时异常,所有的异常都需要在编写程序阶段对其进行预处理,将是怎样的效果呢?
首先,如果这样得话,程序肯定时绝对安全的。但是程序员编写程序太累,代码导出都是处理异常的代码。

Java语言中对异常的处理包括两种方式:

第一种方式:在方法声明的位置上,使用throws关键字,抛给上一级。谁调用我这个方法,我就抛给谁。抛给调用者来处理。
这种处理异常的方式:上报。
第二种方式:使用try..catch语句进行异常的捕捉。
这个异常不会上报,自己把这个事儿处理了。异常抛到此处为止,不再上抛了。

异常发生之后,如果我选择上抛,抛给了我的调用者,调用者需要对这个异常继续处理,那么调用者处理这个异常同样有两种处理方式。

注意:Java中异常发生之后如果一直上抛,最终抛给了main方法,main方法继续向上抛,抛给了调用者JVM,JVM知道这个异常发生,只有一个结果,终止java程序的执行。

throws后面可以写多个异常,可以使用逗号隔开。

注意:只要异常没有捕捉,采用上报的方式,后续代码不会执行。
另外要注意:try语句块中的某一行出现异常,该行后面的后面的代码不会执行。

深入try..catch
catch后面的小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型。
catch可以写多个。建议catch的时候,精确的一个一个处理。这样有利于程序的调试。
catch写多个的时候,从上到下,必须遵守从小到大。

JDK8新特性
catch小括号里面可以写多个异常中间用”|“或符号隔开

在以后的开发中,处理编译时异常,应该上报还是捕捉呢,怎么选?
如果希望调用者来处理,选择throws上报。
其他情况使用捕捉的方式。

异常对象的常用方法

异常对象有两个非常重要的方法:

获取异常简单的描述信息:这个信息实际上就是构造方法上面String参数。
String msg = exception.getMessage();

打印异常追踪的堆栈信息:
java后台打印异常堆栈追踪信息的时候,采用了异步线程的方式打印的。
exception.printStackTrace();

我们以后查看异常的追踪信息,我们应该怎么看,可以快速的调试程序呢?
异常追踪信息,从上往下一行一行看。
但是需要注意的是:SUN公司写的代码就不用看了。(看包名就知道是自己的还是SUN的。)主要的问题是出现在自己编写的代码上

关于try..catch中的finally子句

在finally子句中的代码是最后执行的,并且是一定会执行的,即使try语句块中的代码出现了异常。
finally子句必须和try一起出现,不能单独编写。
放在finally语句块中的代码时一定会执行的。

finally语句通常使用在哪些情况下呢?
通常在finally语句块中完成资源的释放/关闭。
因为finally中的代码比较有保障。
即使try语句块中的代码出现异常,finally中代码也会正常执行。

try和finally,没有catch可以么?可以
try不能单独使用。
try finally可以联合使用

System.exit();//退出JVM

退出JVM之后,finally语句中的代码就不执行了!

finally面试题

public class Text{
  public static void main(String[] args){
    int result = m();
    System.out.println(result);//100
  }

  public static int m(){
    int i = 100;
    try{
          return i;
        }finally{
                      i++;
                    }
  }
}

问这个输出结果是什么?
result的结果是100

反编译之后的效果是这样的

public static int m(){
  int i = 100;
  int j = i;
  i++;
  return j;
}

java语法规则(有一些规则是不能破坏的,一旦这么说了,就必须这么做)
java中有一条这样的规则:
方法体中的代码必须遵循自上而下顺序依次逐行执行(亘古不变的语法!)
java中还有一条语法规则:
return语句一旦执行,整个方法必须结束(亘古不变的语法!)

final finally finalize有什么区别?
final是一个关键字。表示最终的,不变的。
finally也是一个关键字,和try联合使用,使用在异常处理机制中。在finally语句块中的代码是一定会执行的。
finalize()是Object类中的一个方法。作为方法名出现。所以finalize是标识符。

final 关键字
final修饰的类无法继承。
final修饰的方法无法覆盖。
final修饰的变量不能重新赋值。

finally 关键字
和try一起联合使用。
finally语句块中的代码时必须执行的。

finalize 标识符
是一个Object类中的方法名。
这个方法是由垃圾回收器GC负责调用的。

自定义异常

SUN提供的JDK内置的异常肯定时不够用的。在实际的开发中,有很多业务,这些业务出现异常之后,JDK中都是没有的。和业务挂钩的。那么异常类我们程序员可以自定义吗?可以。

Java中怎么自定义异常呢?
第一步:编写一个类继承Exception(编译时异常)或者RuntimeException(运行时异常)。
第二步:提供两个构造方法,一个无参数的,一个带游String参数的。
死记硬背就行了。

public class MyException extends Exception{
  public MyException(){
  }

  public MyException(String s){
    super(s);
  }
}

在以后的程序里面凡是出现异常的地方,你都可以通过throw new的方式去手动抛异常。

重写之后的方法不能比重写之前的方法抛出更多(更宽泛)的异常,可以更少。

以后开发的时候方法重写,就直接复制粘贴父类的就行了。

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

推荐阅读更多精彩内容