## **一、什么是错误异常**
在程序编译或运行过程中出现了非人为预期或者人为可预期的错误,该错误导致后续程序无法继续编译或者继续运行称之为异常。
>[info] 程序的编译至运行,可以举例为:你计划明日骑车至北京,那么分为以下两个过程:
> 1. 从有想法到正式出发,我们假设为计划过程,也可以视为程序的编译过程,如果在整个计划中发现明天要下雨,这个可以视为是可预计也有可能不可预计(天气预报说晴朗,但在出发那一刻电闪雷鸣),但总归这样的情况是无法再进行下去的,所以可以称为编译错误,导致程序后续终止。
> 2. 从出发到目的地,我们可以假设为程序的运行阶段。在这个过程中,可能会发生一些突发情况,如:车胎漏气、爆胎、出交通事故等,但总归再整个计划到实施过程中会发生影响计划或终止计划的情况,我们将它称为错误或异常。
>
> 所以说错误和异常都是在程序编译或执行过程中发生的预期或没有预期到的情况,但如果要细致区分,可以以能否继续执行去划分,发生错误寓意着后续无法继续执行,发生异常寓意着后续可能还能够执行,只是执行过程中偏离了我们预期的轨道。在Java中,编译异常我们不可控制,只可控运行错误异常也可以由我们自己去抛出。
~~~java
public class run {
public static void main(String [] args){
// 假设a、b均为用户输入
int a = 1;
int b = 0;
try{
int c = a/b;
}catch (Exception e){
throw new RuntimeException("输入数值不符合计算要求:" + e.getMessage());
}
}
}
================================ 运行结果 ================================
Exception in thread "main" java.lang.RuntimeException: 输入数值不符合计算要求:/ by zero
at run.main(run.java:10)
~~~
<br/>
## **二、Java里常见的错误异常**
1. 编译错误:新手比较多,如语法错误、声明错误、使用错误;
2. 运行时错误:程序在执行时,由于传入参数不符合预期或计算结果不符合要求;
3. 逻辑错误:程序没有按照原定的逻辑进行运行。
>[info] Java中的`Java.lang`的软件包中有一个`Java.lang.Throwable`类,这个类是Java中所有错误和异常的超类,`Throwable`类有两个子类,`Error`与`Exception`
* **Error - 错误**
* Throwable的子类,其中也包含大量子类
* 出错后程序无法继续进行,如内存溢出等
* **Exception - 异常**
* Throwable的子类,其中也包含大量子类
* 程序本身可以处理的异常
* 分为两大类:
* **可查异常**(编辑器要求必须处理的异常):`RuntimeException`及其子类以外,其他的`Exception`类及其子类,如`IOException`和`ClassNotFoundException`;
* **不可查异常**(编辑器不要求强制处理的异常):包括运行时异常(`RuntimeException`及其子类)和错误(`Error`),如`ArrayIndexOutOfBoundsException`
:-: ![](images/Java中的异常.png)
## **三、如何在代码编写中使用异常**
1. 可预见的异常我们可以使用`try cache`进行预期捕获,如下:
~~~java
try{
// 可能会发生异常的代码
}catch (ExceptionNameA e){
// 发生A异常时的处理
}catch (ExceptionNameB e){
// 发生B异常时的处理
}finally{
// 肯定要执行的代码放这里
}
// 例如上面刚开始的例子 我们在粘下来注释看看
public class run {
public static void main(String [] args){
// 假设a、b均为用户输入
int a = 1;
int b = 0;
try{
int c = a/b; // 被除数不能等于0,这里正常会报ArithmeticException异常
}catch (Exception e){
/**
* 此处我们使用Exception类去接异常,ArithmeticException属于Exception类,如果知道具体的异常
* 的话(如此处的ArithmeticException),我们可以更换成`ArithmeticException e`去定义e的数
* 据类型,甚至可以使用`Throwable e`,因为ArithmeticException是Exception的子类,而Exception
* 又是Throwable的子类
*/
/**
* 在这我们用了一个抛出异常,当然你也可以不用抛出,但在这的逻辑中如果b为0,那么c的结果肯定是我们不
* 能接受的,所以我们通过抛出异常来 *终止* 程序进行,异常的抛出也有各种如:
* // 这是抛出了运行异常
* throw new RuntimeException("输入数值不符合计算要求:" + e.getMessage());
* // 这是抛出了计算异常
* throw new ArithmeticException("输入数值不符合计算要求:" + e.getMessage());
*
* 如果c的结果不影响你的使用,那你可以不抛出异常,继续让程序走下去:
* System.out.println("警告:输入数值不合法");
* //throw new RuntimeException("输入数值不符合计算要求:" + e.getMessage());
*
*/
throw new RuntimeException("输入数值不符合计算要求:" + e.getMessage());
}
}
}
~~~
>[info] 在我们写代码的过程中,我们可以通过定义异常的方式来对程序进行判断是否能够继续下去
2. `throw`和`throws`的区别
* `throw` 可以让我们在代码中的某个地方抛出异常,但如果在类的定义中我们使用了`throws`,则这个异常则是抛给了方法调用的代码块:
~~~
public class Compute {
// 此处我们将错误抛出给调用代码
public int compute(int a, int b) throws Exception{
int c = 0;
try{
c = a/b;
return c;
}catch (ArithmeticException e){
// 所以这里的错误抛给了调用函数,编辑器需要调用函数使用try-catch去捕获错误
throw new Exception("输入数值不符合计算要求:" + e.getMessage());
}
}
}
public class run {
public static void main(String [] args){
// 假设a、b均为用户输入
int a = 1;
int b = 0;
try {
Compute compute = new Compute();
int result = compute.compute(a,b);
System.out.println("result"+result);
}catch (Exception e){
// 捕获错误
System.out.println(e.getMessage());
}
System.out.println("程序结束");
}
}
================================ 运行结果 ================================
输入数值不符合计算要求:/ by zero
程序结束
进程已结束,退出代码0
~~~