# 异常处理
[TOC]
## 为什么会出现异常
>[danger] 用户不正当的输入
> 本身系统的问题
## 为什么要处理异常
~~~
public class ExceptionStudy {
public static void main(String[] args) {
System.out.println("******程序开始运行*******");
System.out.println("******数学计算:"+ (10/2) +"*******");
System.out.println("******程序运行结束*******");
}
}
运行结果:
******程序开始运行*******
******数学计算:5*******
******程序运行结束*******
public class ExceptionStudy {
public static void main(String[] args) {
System.out.println("******程序开始运行*******");
System.out.println("******数学计算:"+ (10/0) +"*******");
System.out.println("******程序运行结束*******");
}
}
运行结果:
******程序开始运行*******
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.ntdodoke.preparation.usuallyClass.ExceptionStudy.main(ExceptionStudy.java:6)
~~~
如果不处理异常,一旦在出现异常的地方,程序就会被「异常指令流」直接终止,不再往下运行。为了让程序在出现异常后依然可以正常执行,所以我们必须正确处理异常来完善代码的编写。
## 处理异常
**使用 try catch**
>[success] 判断一个对象是否为空,使用`null != str`
在程序方法设计,特别是方法的实现中,对于传入的参数,是不可知的,所以要对传入的参数进行最基础的验证后,才能使用,例如,判断是否为 null。尽量猜测可能会发生的问题,确保异常的少发生和不会发生
~~~
public static void main(String[] args) {
fun1("",null);
fun2();
}
public static void fun1(String str, String subStr) {
if (null != str && null != subStr) {
if(str.indexOf(subStr) >= 0) {
System.out.println("存在子串");
} else {
System.out.println("不存在子串");
}
} else {
System.out.println("不合法字符串");
}
}
public static void fun2() {
System.out.println("++++++++++++++");
System.out.println("继续执行");
System.out.println("++++++++++++++");
}
~~~
在 try catch 结构中,catch 是可以省略的,也可以多异常的捕获,但是出现多异常的时候,父类异常只能出现在最下面。
在实际的开发中,一般最简单的方式就是使用一个 Exception 直接处理。
~~~
public class ExceptionStudy {
public static void main(String[] args) {
fun1("",null);
fun2();
}
public static void fun1(String str, String subStr) {
try{
if (str.indexOf(subStr) >= 0) {
System.out.println("存在子串");
} else {
System.out.println("不存在子串");
}
int a = 10/0;
} catch(NullPointerException e) {
System.out.println("出现空指针异常");
System.out.println("输入非法字符");
//e.toString(): 获得异常种类和错误信息
//e.getMessage():获得错误信息
//e.printStackTrace():在控制台打印出异常种类,错误信息和出错位置等
e.printStackTrace();
System.out.println(e.getMessage());
System.out.println(e.toString());
} catch(ArithmeticException e1) {
e1.printStackTrace();
} finally {
System.out.println("finally中的内容无论发不发生异常都会执行");
}
}
public static void fun2() {
System.out.println("++++++++++++++");
System.out.println("继续执行");
System.out.println("++++++++++++++");
}
}
~~~
**使用 finally**
无论是否出现异常都会被执行,特别要注意的是,如果没有写 catch ,那么 finally 是会被执行的,但是中断后的语句是不会被执行的。
~~~
public class ExceptionStudy {
public static void main(String[] args) {
fun1("",null);
fun2();
}
public static void fun1(String str, String subStr) {
try{
if (str.indexOf(subStr) >= 0) {
System.out.println("存在子串");
} else {
System.out.println("不存在子串");
}
} finally {
System.out.println("finally中的内容无论发不发生异常都会执行");
}
}
public static void fun2() {
System.out.println("++++++++++++++");
System.out.println("继续执行");
System.out.println("++++++++++++++");
}
}
~~~
**throws**
在**方法定义**的后面显式的声明方法是有异常的,调用该方法的程序是要显式的处理异常,后者也可以再次抛出。
~~~
public class ExceptionStudy {
public static void main(String[] args) {
try {
fun3();
} catch(NullPointerException e) {
e.printStackTrace();
}
fun2();
}
public static void fun1(String str, String subStr) throws NullPointerException {
if(str.indexOf(subStr) >= 0) {
System.out.println("存在子串");
} else {
System.out.println("不存在子串");
}
}
public static void fun2() {
System.out.println("**********************");
System.out.println("继续执行");
System.out.println("**********************");
}
public static void fun3() throws NullPointerException {
fun1("aaa",null);
System.out.println("aaaaaaa");
}
}
~~~
**throw**
自定义的创建一个异常对象。在一般的异常发生时候,虚拟机会动态的创建一个「系统异常」抛出,和自定义使用 throw 抛出是一个概念。
~~~
public class Demo3 {
public static void main(String[] args) throws Exception {
fun1(17);
System.out.println("end");
}
public static void fun1(int age) throws Exception {
if (age < 18) {
throw new Exception("您的年龄不合法");
} else {
System.out.println("您已经进入VIP房间");
}
}
}
~~~
`throws`和`throw`的区别
throws是指方法可能会发生异常
throw则是通过语句抛出异常,当执行throw语句的时候异常已经发生了
## 异常堆栈信息
* 异常类
* 异常提示信息:getMessage()
* 异常所在的代码位置:自下而上是异常出现的代码所在方法的调用顺序的先后。
## 常见的异常
NPE:NullPointerException 在调用对象属性或者方法的时候,对象其实是个 null,就会报此异常;
java.lang.ArrayIndexOutOfBoundsException:数组越界
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1:集合越界