zoukankan      html  css  js  c++  java
  • 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抛出的是异常对象。

  • 相关阅读:
    codevs1004 四子连棋
    codevs1009 产生数
    NOIP2014 寻找道路
    Tyvj1139 向远方奔跑(APIO 2009 抢掠计划)
    随机算法
    线性基
    线性基入门
    线性基 + 并查集
    欧拉公式 (平面)
    卡特兰数 + 大数
  • 原文地址:https://www.cnblogs.com/sunchuanzhen/p/3359068.html
Copyright © 2011-2022 走看看