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
浙公网安备 33010602011771号