java学习面向对象之异常之一

一、异常的概述:

  什么是异常?在我们编写java程序的时候,会出现一些问题,比如内存溢出啊或者数组索引超出最大索引啊,这些编程当中出现的这些个问题就是异常。但是异常也分为可以处理的和不可以处理的。比如JVM虚拟机出现的异常就是不可以处理的。可以处理的异常就是指,在我们java程序当中的数组最大索引超出啊,这些问题我们是可以处理的。同时异常也分为Error和Exception。从字面意义上来理解的话,可以理解成错误和异常。Error指在JVM运行当中出现异常,程序自动退出。下面我们来写个例子看下什么是异常?

 1 class Demo1
 2 {
 3     
 4     int[] arr = new int[3];
 5 
 6 }
 7 
 8 class ExcepDemo1
 9 {
10     
11     public static void main(String[] args) {
12         
13         Demo1 demo = new Demo1();
14         System.out.println(demo.arr[6]);
15 
16     }
17 
18 }

因为这个地方我们的数组索引超出了最大值,这里就提示我们:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6

如果我们这里出现语法错误又会怎样呢?

既然出现了异常,我们就要去修正。修正的方法有哪些呢,比如上面的索引溢出异常,这个时候,我们就得在代码当中来判断,如果索引大于最大值,我们应该怎么办。在处理错误的时候就得写很多的代码,来描述现在反生的异常是怎样的,在什么地方等等异常的信息。java是一门面向对象的语言,面向对象的特点之一就是封装,也就是把属性还有方法封装到一个类当中,这样就方便了我们的调用,以前是正常代码和异常处理代码结合,现在是把正常代码和异常处理代码分离,同时也提高了代码的复用性。在java当中,为了方便我们来处理异常,提供了一个异常类Exception给我们。其实异常就是java通过面向对象的思想将问题封装成对象,然后用异常类来描述。不同的问题,用不同的异常类进行描述。

问题很多,意味着描述类也很多,将其共性不断向上抽取,就形成了异常体系。对于体系而言,父类当中定义的都是最共性的东西。

最终问题 不正常情况分为两大类:

  1、一般不可处理的。用Error类来表示。比如java xx 如果xx这个javaclass 不存在就会Error。一般由JVM抛出的,这种问题发生不会针对性处理,直接修改程序。

  2、可处理的。用Exception类来表示, 可以进行针对性的处理

无论Error还是Exception,发生问题后,都要抛出。该体系的特点是throwable及其所有他的子类都有可抛性。

就像人生活中得病一样,一种是可治愈的,一种是不可治愈的。Error就是不可治愈的范畴了,Exception可以治愈的。

子类都是以其父类名作为后缀,阅读性就很强。

但是两者都有共性,向上抽取之后就是throwable。那么怎么体现可抛性呢?通过两个关键字来体现的,一个是throws,一个是throw。凡是可以被这两个关键字可以操作的类或者对象,都具有可抛性。

 

那么异常的执行流程也就是内部原理是怎样的呢?当出现异常的时候,首先调到功能定义的部分,如果功能定义的部分没有处理,继续网上抛出,直至被处理。如果自始至终都没有被处理的话,这个时候,就会把异常抛给虚拟机。虚拟机收到异常之后,停止程序的执行然后把异常的相关信息直接打印到控制台上面。

 

比如上述索引越界,我们可以这个样子来写:

 1 class Demo1
 2 {
 3     
 4     int[] arr = new int[3];
 5 
 6 }
 7 
 8 class ExcepDemo1
 9 {
10     
11     public static void main(String[] args) {
12         
13         Demo1 demo = new Demo1();
14         int num=6;
15         if(num>demo.arr.length){
16 
17             throw new Exception("the num is too large");//我们new完了异常之后,这个时候为了能够让调用者知道异常原因,这个时候我们引入了throw这个关键字
18 
19         }else{
20 
21             System.out.println(demo.arr[num]);
22 
23         }
24 
25     }
26 
27 }

throw和return的区别,有的人会说我们不用throw用return,这个就涉及工作的一个完成一个未完成,一个事情的完成是有结果的,使用return的作用就是返回结果。throw的作用就是终止现在的事情出异常了,没法继续下去了,没有结果就。比如,你让一个人去做一件事情,做到一半的时候,那个人感冒了,没法做下去了,就把信息返回给你说“我感冒了,这件事做不下去了”,这个时候这件事没有结果了就。所以不能用return。但是throw是有前提的,必须具有可抛性。

这个时候我们javac编译的话,真的出现异常啦:

这里提示我们要对未报告的异常错误进行捕捉或者声明,那么为什么要声明一个异常呢,声明的意思就是说他可能会出现什么错误。我们设计一个功能,这个功能(函数)可能会出现异常,我们知道他可能出现哪些异常,比如你买了一个面包要给我吃,面包放了三天了,你得最起码要在面包上面贴个标签说:面包可能坏了。这个就是声明,方便我就可以采取相应的措施进行处理。如何声明一个异常呢?这里又用到了一个关键字叫做throws,但是这个声明是有条件的,thorws是给函数修饰的,谁可能出现异常就声明谁。如果函数可能会出现异常,我们要在函数上声明异常,否则会编译失败。如果调用了声明异常的函数,你必须要处理,不处理一样也是编译失败,处理问题之一就是抛出问题。最终把异常抛给虚拟机了。

也就是说要想让一个类成为异常类,必须先让他继承异常体系,因为只有具备异常体系的共性,才具有可抛性,才可以被throws 还有 throw来操作。

修改代码如下:

 1 class Demo1
 2 {
 3     
 4     int[] arr = new int[3];
 5 
 6 }
 7 
 8 class ExcepDemo1
 9 {
10     
11     /**
12     *这个main方法可能出现错误,所以这个时候就该throws Exception 声明这个异常
13     */
14     public static void main(String[] args) throws Exception
15     {
16         
17         Demo1 demo = new Demo1();
18         int num=6;
19         if(num>demo.arr.length){
20 
21             throw new Exception("the num is too large");
22 
23         }else{
24 
25             System.out.println(demo.arr[num]);
26 
27         }
28 
29     }
30 
31 }

抛出的异常结果为:

这里就是我们自定义的异常信息。但是我们发现这个异常信息提示的是java.lang.Exception,如果冷不丁来这么个异常,我们也不知道问题出在那里哇?肿么办?我们自定义个非常好理解的异常来说下,如何定义一个异常?我们只需要定义一个类然后继承自Exception,然后覆盖相应的方法就可以了。下面我们来自定义一下:

 1 /**
 2 *这个地方我们命名的时候最好是以Exception结尾,这样可以增强阅读性
 3 */
 4 class MyOutofArrayIndexException extends Exception
 5 {
 6     /**继承完之后,我们来覆盖下Exception当中的方法,具体方法去查手册可知**/
 7     public MyOutofArrayIndexException(String s)
 8     {
 9 
10         super(s);
11 
12     }
13 
14 }
15 
16 class Demo1
17 {
18     
19     int[] arr = new int[3];
20 
21 }
22 
23 class ExcepDemo1
24 {
25     
26     /**
27     *这个main方法可能出现错误,所以这个时候就该throws Exception 声明这个异常
28     */
29     public static void main(String[] args) throws MyOutofArrayIndexException
30     {
31         
32         Demo1 demo = new Demo1();
33         int num=6;
34         if(num>demo.arr.length){
35 
36             throw new MyOutofArrayIndexException("the num is too large");
37 
38         }else{
39 
40             System.out.println(demo.arr[num]);
41 
42         }
43 
44     }
45 
46 }

此时运行之后就体现了我们自定义的异常信息了。

 

那么我们每次调用个自定义的异常多麻烦啊,我们要是不用声明异常该多好啊。我们知道在我们第一个写的来演示异常的代码的时候,我们并没有声明异常啊,不也是照样过了。为什么自定义就要声明呢?这是因为啊,在我们没写的情况下,当时调用的是RuntimeException这个对象有个特点就是,编译的时候并不对他进行检查,只有在执行的时候才检查,如果有异常就调用。这样多好,我们不用声明啦,直接继承他看看。

 1 /**
 2 *这个地方我们继承了RuntimeException,也就是运行时异常,编译时并不检查
 3 */
 4 class MyOutofArrayIndexException extends RuntimeException
 5 {
 6 
 7     public MyOutofArrayIndexException(String s)
 8     {
 9 
10         super(s);
11 
12     }
13 
14 }
15 
16 class Demo1
17 {
18     
19     int[] arr = new int[3];
20 
21 }
22 
23 class ExcepDemo1
24 {
25     
26 
27     public static void main(String[] args)
28     {
29         
30         Demo1 demo = new Demo1();
31         int num=6;
32         if(num>demo.arr.length){
33 
34             throw new MyOutofArrayIndexException("the num is too large");
35 
36         }else{
37 
38             System.out.println(demo.arr[num]);
39 
40         }
41 
42     }
43 
44 }

这个是编译通过的。

异常的分类:

  1、编译时被检测异常:Exception 和 其子类 除了 RuntimeException类除外都是。这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应针对的处理方式。

  2、编译时不检测异常(运行时检测)RuntimeException 及其子类都是,编译器并不检测这个。这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的,或者引发了内部状态的改变导致的。这种问题一般不处理,在运行时,让程序强制停止,让调用者对代码进行修改。RuntimeException是在正常运行之中,出现异常。而Error直接让虚拟机停掉。

自定义异常一个是继承Exception一个是继承自RuntimeException。

throw throws的区别

  throws使用在函数上,throw是用在函数当中。

  throws 声明异常类,可以声明多个,throw抛出的是异常对象。

posted @ 2013-10-09 13:40  stark_javac  阅读(232)  评论(0编辑  收藏  举报