Exception in thread "main" java.lang.ArithmeticException: / by zero at ExceptionDemo01.main(ExceptionDemo01.java:6)

  控制台突然造反了,不按照我想的结果打印了!定睛一看 ArithmeticException;这是啥东西?

  ............

  不知过了多久!I know 了~,且看下面:

 

  一、什么是异常?

 1.1、简单描述

  异常是在程序中导致程序中断运行的一种指令流。如图所示(发生的流程)

  1.2、异常的分类

     

   

  • 检查性异常(受检异常):最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
  • 运行时异常(非受检异常 RuntimeException): 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
  • 错误(Error): 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

  二、异常处理

  2.1、try  catch 处理 

    使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。try/catch代码块中的代码称为保护代码,使用 try/catch 的语法如下:

 

try{
  // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}finally{
  // 程序代码
}

  代码执行的顺序:
      * 1.try内的代码从出现异常的那一行开始,中断执行
      * 2.执行对应的catch块内的代码
      * 3.继续执行try catch结构之后的代码
    *注意点:
      * 1.如果catch内的异常类存在子父类的关系,那么子类应该在前,父类在后
      * 2。如果最后中有返回语句,那么最后返回的结果肯定以最终中的返回值为准
      * 3。如果最后语句中有回报,那么没有被处理的异常将会被吞掉
    *重写的注意点:
      * 1.儿子不能比父亲的本事大
      * 2.儿子要比父亲开放
      * 3.儿子不能比父亲惹更大的麻烦(子类的异常的类型不能是父类的异常的父类型)
    *异常类Api:
      * 1。的getMessage():获取异常描述信息字符串
     * 2。的toString():返回异常类的包路径和类名和异常描述信息字符串  * 3。的printStackTrace():除了打印的toString的信息外,还要打印堆栈信息

 上面一段注释来自网上这位博主的,觉得写的很好,传送门地址:https://blog.csdn.net/wanghuiwei888/article/details/78818203 

 2.2.2 还有另外一种写法

  特殊的多异常捕获写法:

catch(异常类型1 |异常类型2 对象名){
//表示此块用于处理异常类型1 和 异常类型2 的异常信息
}

  2.2.3 finally

  在进行异常的处理之后,在异常的处理格式中还有一个finally语句,那么此语句将作为异常的统一出口,不管是否产生了异常,最终都要执行此段代码(断电,电脑坏了,或者try里面写了终止程序执行语句的System.exit("0"))

  特别注意,先看图!!!

  图一

 

图二

    

  图一p的返回值为28,图二a的返回值为10;

  原因是:p是属于引用类型,对象存在堆里面,栈里面新备份的是引用的地址,所以finally执行后引用的地址没变,对应的值变了;

      a是属于基本类型,值存在栈中,return的时候是新备份的a,和int a 这个变量没有关系了。

  补充一点(面试题):  

    1、try-catch-finally 中哪个部分可以省略?
      答: catch和finally可以省略其中一个 , catch和finally不能同时省略
      注意:格式上允许省略catch块, 但是发生异常时就不会捕获异常了,我们在开发中也不会这样去写代码.

    2、try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?
      答:finally中的代码会执行
      详解:
      执行流程:
      1. 先计算返回值, 并将返回值存储起来, 等待返回
      2. 执行finally代码块
      3. 将之前存储的返回值, 返回出去;
      需注意:
      1. 返回值是在finally运算之前就确定了,并且缓存了,不管finally对该值做任何的改变,返回的值都不会改变
      2. finally代码中不建议包含return,因为程序会在上述的流程中提前退出,也就是说返回的值不是try或catch中的值
      3. 如果在try或catch中停止了JVM,则finally不会执行.例如停电- -, 或通过如下代码退出JVM:System.exit(0);

    3、RuntimeExcepion与Exception的区别   

      注意观察如下方法的源码:
      Integer类: public static int parseInt(String text)throws NumberFormatException
      此方法抛出了异常, 但是使用时却不需要进行try。。。catch捕获处理,原因:
      因为NumberFormatException并不是Exception的直接子类,而是RuntimeException的子类,只要是RuntimeException的子类,则表示程序在操作的时候可以不必使用try…catch进行处理,如果有异常发生,则由JVM进行处理。当然,也可以通过try catch处理。

  2.2.4、  throws  

    如果一个方法没有捕获到一个检查性异常,那么该方法必须使用 throws 关键字来声明。此关键字主要在方法的声明上使用,表示方法中不处理异常,而交给调用处处理。   

    格式:
    返回值 方法名称()throws Exception{
    }

    一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。

    例如:

import java.io.*;
public class className
{
   public void withdraw(double amount) throws RemoteException,
                              InsufficientFundsException
   {
       // Method implementation
   }
   //Remainder of class definition
}

  2.2.5、  throws

    throw关键字表示在程序中人为的抛出一个异常,因为从异常处理机制来看,所有的异常一旦产生之后,实际上抛出的就是一个异常类的实例化对象,那么此对象也可以由throw直接抛出。  

    代码: throw new Exception("抛着玩的。") ;

import java.io.*;
public class className
{
  public void deposit(double amount) throws RemoteException
  {
    // Method implementation
    throw new RemoteException();
  }
  //Remainder of class definition
}

 三、自定义异常类    

  在 Java 中可以自定义异常。编写自己的异常类时需要记住下面的几点。

 

  • 所有异常都必须是 Throwable 的子类。
  • 如果希望写一个检查性异常类,则需要继承 Exception 类。
  • 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。

 

  编写一个类, 继承Exception,并重写一参构造方法 即可完成自定义受检异常类型。
  编写一个类, 继承RuntimeExcepion,并重写一参构造方法 即可完成自定义运行时异常类型。

class MyException extends Exception{ // 继承Exception,表示一个自定义异常类
public MyException(String msg){
super(msg) ; // 调用Exception中有一个参数的构造
}
};
class MyException extends Exception{
public MyException(String msg){
super(msg) ;
//在这里给维护人员发短信或邮件, 告知程序出现了BUG。
}
};

  到这里,异常及处理就都差不多咯~ end