<<异常>>---黑马程序员

--------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------

1.异常概述

异常:异常就是程序在运行时出现的不正常的情况。

   异常问题分为:严重问题和非严重问题。

    Throwable

        |-----Error:表示严重问题

            对于此问题一般不会对此异常进行代码的处理

        |-----Exception:表示非严重问题

             对于此问题会进行对此异常进行代码的处理。

2. 异常的处理

       2-1. 在本方法中处理

                     1.处理方式:

                                          try{}catch(异常对象 变量)finally{}

                try{}catch(异常对象 变量)

                try{} finally{}

                       2.处理规则:

              在try{检测的代码}catch(捕获的异常)finally{一定会执行的代码(在虚拟机没有停止的前提下)}例如如果在finally{}前面有System.exit(0)的话,那么虚拟机就会停止,后面的代码自然不会执行。

 在catch(异常类 变量)捕获异常的时,会按照顺序进行捕获,然后进行处理,所以在写catch()的时候,一定要把子类或者方法抛出的异常写到前面,异常的父类写在后面,例如:一定要把Exception写到最后面catch(Exceptione)


public class ExceptionDemo {
  public static void main(String[] args) {
    try {
      div(4, 0);
    } catch (ArithmeticException e) {// 除零异常
      e.printStackTrace();
    } catch (Exception e) {// 防止有其他的异常没有处理,但是如果把此位置的放到捕获异常的最前面,
      e.printStackTrace(); // 那么后面的捕获异常就会没有自导作用,
                           // 因为此是父类,是按照顺序执行
    }
  }
  public static void div(int a, int b) {
    System.out.println(a / b);
  }
}

                       3.异常的信息的输出方式

System.out.println("被零除了!");//自定义的信息

      System.out.println(e.getMessage());//异常信息:    / by zero

      System.out.println(e.toString());//异常包.类名  :异常信息  java.lang.ArithmeticException: / by zero

      e.printStackTrace();//异常包.类名:异常信息 异常位置

      /*

       java.lang.ArithmeticException: / by zero

  at www.fuxi.yichang.ExceptionDemo.div(ExceptionDemo.java:18)

  at www.fuxi.yichang.ExceptionDemo.main(ExceptionDemo.java:6)

*/

e.getMessage()-----》e.toString()----》e.printStackTrace()他们的输出的信息是越来越详细的,但是在开发中,我们是不这样处理的,因为用户是看不懂异常信息并且处理不了的,所以我们是把错误信息写入到一个文件中,然后供管理员查看,来处理异常,这样就可以优化系统程序。

 

        2-2.抛出

                            1.如何抛出

               使用throws关键字来抛出异常,在方法中对处理课程出现的异常,在方法的声明上进行抛出,这样在调用此方法的时候,必须在调用此方法的方法中进行处理此异常或者继续抛出,那么这样就可以防止用处在不知情的情况下输入的不正确的信息,就会进行必须的处理,防止程序的结束。

                             2.抛出声明的规则:

                   声明异常时,声明的异常要更为详细,这样处理的时候就为具体

          对方声明了几个异常,那么我们就处理几个异常,或者抛出几个异常。

          

public class ExceptionThrow {
  public static void main(String[] args) {
    try {
      div(4, 0);// 除数方法
    } catch (ArithmeticException e) {// 除零异常
      System.out.println("被零除了!"); // 自定义的信息
    } catch (Exception e) {
      e.printStackTrace();
 
    }
  }
  public static void div(int a, int b) throws ArithmeticException {
    System.out.println(a / b);
  }
}


 

3. 自定义异常。

     3-1.自定义异常的规则

          1.自定义异常的了类必继承Exception类。然后你可以重新其中的方法或者直接调用就看你的意向了。

     2.继承Exception类的原因,因为你的在Throwable类体系中的类或者是对象需要被抛出,但是只有此Throwable体系中的对象才能被抛出,所以要继承Throwable类或者是子类。可以是Error或者是Exception。

     3.自定义的异常要不在本方法中处理了,要不就抛出。(不是继承的RuntimeException类)

    4.我们可以定义自己需要的异常,没有给提供的异常,系统中的提供的不够我们使用的,可以按照自己的来自己定义,

     3-2.代码举例。

  /*自定义的异常*/
class MyDivFuShuException extends Exception {
  public MyDivFuShuException(String message) {
    super(message);
  }
}
 
public class ZidingyiException {
  public static void main(String[] args) {
    try {
      div(1, -1);
    } catch (MyDivFuShuException e) {// 这里捕获的是方法中抛出的异常
      System.out.println(e.getMessage());
    }
        div1(1, -1);
  }
 
  /* 自定义的异常把异常抛出 */
  public static void div(int a, int b) throws MyDivFuShuException {
    if (b < 0)
      throw new MyDivFuShuException("自定义的异常,除数不能为零");
    System.out.println(a / b);
  }
 
  /* 自定义的异常在本方法中就把异常抛出 */
  public static void div1(int a, int b) {
    try {
      if (b < 0)
         throw new MyDivFuShuException("自定义的异常,除数不能为零");
      System.out.println(a / b);
    } catch (MyDivFuShuException e) {
      System.out.println(e.getMessage());
    }
  }
 
}


 

         3-3.throw和throws的区别

         Throws是定义在了函数上,后面可以跟多个异常类,用逗号隔开。

       Throw是定义在函数内,后面跟的是异常对象,只能跟一个对象。

4. RuntimeException

     4-1.异常分类。

            可以分为编译时可以被检测的异常

      表示的是Exception类或者是子类,或者是自定义的异常继承的此类,对于此异常的类必须进行try{}处理,或者抛出,并且要进行捕获,要不编译会出现错误,可以参考上面将的Exception

      编译时不被检测的异常(运行时异常,RuntimeException以及子类)

     4-2.运行时异常的特点

           1.在方法体中抛出了运行是异常或者是其子类的话,那么在方法上不用声明抛出的次异常,就是不需要用throws在方法上声明

           2.在方法上声明了抛出的运行时异常或者是其子类,那么不需要在调用处,不用进行捕获和处理。

           3.在运行时出现了运行是异常,那么必须停止了程序,然后有调用者进行在出错的程序上进行更改和调试。

          4.如果要求自定义的异常需要停止程序来运行,那么就让自定义的异常继承RuntimeException类。

        

 public class RuntimeExceptionDemo {
  public static void main(String[] args) {
    /* ArithmeticException类是RuntimeException的子类 */
    Div(2,0);
    DivThrow(2,0);
  }
 
  /**
   * 在此方法中抛出的是RunntimeException子类,此时不需要在方法上声明抛出的此异常
   * 编译是不会出错,因为RunntimeException是运行时异常,
   */
  public static void Div(int a, int b) {
    if (b == 0) {
      throw new ArithmeticException("除数不能为零");
    }
    System.out.println(a / b);
  }
  /**
   * 在此方法中上声明的是是RunntimeException子类,
   * 此时在调用处是不需要声明捕获此异常,也可以编译通过
   *  因为RunntimeException是运行时异常
   */
  public static void DivThrow(int a, int b) throws ArithmeticException {
    if (b == 0) {
      throw new ArithmeticException("除数不能为零");
    }
    System.out.println(a / b);
  }
 
}
 

5. 异常注意点和技巧

                    当遇到了异常,如果最终有办法出来的话,那么就把捕获到的异常,进行处理的时候,抛给可处理的异常类(catch(xxException e)(throw newkechuliException()))然后这样就可以进行处理了。

      在throw new 异常对象,后面不要写任何代码,因为只要throw抛出了异常,后面就能写代码了。{ throw new 异常对象; 在此代码块的范围内,在后面不能写任何代码了}

6. finally的使用

           finally{一定会执行的代码}:

          一般都是可肯定会执行的代码

          大多数都是要执行的就是资源的关闭。一般都是关闭数据库的连接

          即使前面有return,finally{}中的代码也一样会执行。

          在finally前面有System.exit(0)的话,那么后面的finally{}不会执行,因为虚拟机都停止了。

 

public class finallyDemo {
  public static void main(String[] args) {
    try {
     
      int a = 5 / 1;
      System.out.println("hello" + a);// 不会执行,因为上面已经出现了异常
    } catch (Exception e) {
      // e.printStackTrace();
      return;
    } finally {
      System.out.println("finally");// 会执行
    }
    System.out.println("over");// 会执行,因为前面更已经把异常处理,所以会执行语句
  }
 
}
 


7. 异常处理的格式

      try{}catch(异常对象)finally{}

      try{}catch(异常对象) f

      try{} finally{}

      catch()是用来匹配异常并且处理的的,如果没有被catch处理,那么必须抛出此异常。声明此异常

8.异常的覆盖

      1.子类在覆盖父类的时,如果父类的方法抛出了异常,那么子类的覆盖方法只能抛出父类抛出的异常或者其子类。

     原因:就是父类在抛出了异常的后,抛给了父类,父类处理的只有自己抛出的异常,所以如果子类抛出了父类没有抛出的异常,那么就不能被处理,所以就会出错误。

      2.如果父类方法抛出多个异常,那么子类在覆盖方法时,只能抛出父类异常的子集。

      3.如果父类或者接口的方法没有异常抛出,子类在覆盖方法时,也不可以抛出异常,如果子类方法发生了异常,那么必须进行try{}catch()处理。但是如果是实现的是接口或者抽象类,或者是子类中没有调用父类的构造方法,子类构造方法可以抛出异常并且声明,因为调用的不是同一个方法。

9. 异常练习

求图形的面积。首先把面积方法抽取出来,然后子啊各个图形对象下进行重写,因为各个图形中有各自不同的属性。

 

class NoValueException extends RuntimeException{
  public NoValueException(String message){
    super(message);
  }
}
interface shape{
  void getArea();
}
class Rec implements shape{
     private int len;
     private int wid;
     public Rec(int len,int wid){
     if(len<=0 || wid<=0)
        throw new NoValueException("数据错误");
     this.wid=wid;
     this.len=len;
     }
  public void getArea() {
    System.out.println(len*wid);
   
  }
 
}
public class ShampDemp{
  public static void main(String[] args) {
    Rec r=new Rec(1,0);
    r.getArea();
    System.out.println("over");
  }
 
}


 

10.  异常执行结构图


11.  一个疑问—请解答

   

 /*自定义的异常*/
class MyDivFuShuException extends Exception {
  public MyDivFuShuException(String message) {
    super(message);
  }
}
 
public class ZidingyiException {
  public static void main(String[] args) {
    try {
      div(1, -1);
    } catch (MyDivFuShuException e) {// 这里捕获的是方法中抛出的异常
      System.out.println(e.getMessage());
    }
    try {
      div1(1, -1);
      // } //catch(MyDivFuShuException e) {//
      // 这里捕获自定一的异常,但是方法中没有抛出才异常,不是即使不会出现的异常的,也可以在这里进行捕获呢啊,那为什么还会出错呢
      //System.out.println(e.getMessage());
    } catch (ArithmeticException e) {// 这里编译不会出错误,这是现有的异常类,捕获不出错误,但是为什么自定义的异常就会出错误呢
      System.out.println(e.getMessage());
    }
  }
 
  /* 自定义的异常把异常抛出 */
  public static void div(int a, int b) throws MyDivFuShuException {
    if (b < 0)
      throw new MyDivFuShuException("自定义的异常,除数不能为零");
    System.out.println(a / b);
  }
 
  /* 自定义的异常在本方法中就把异常抛出 */
  public static void div1(int a, int b) {
    try {
      if (b < 0)
         throw new MyDivFuShuException("自定义的异常,除数不能为零");
      System.out.println(a / b);
    } catch (MyDivFuShuException e) {
      System.out.println(e.getMessage());
    }
  }
 
}
 
解答:点击这里


-------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值