1.相关概念:
(1)异常是程序运行时产生的一种问题(不是编译期)
(2)异常的种类有很多,不同种类的异常能够表示不同情况的问题
2.基本语法:
示例:
public class Abnormal {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4};
try {
System.out.println("before");
System.out.println(arr[100]);
System.out.println("after");
} catch (ArrayIndexOutOfBoundsException e) {
//打印出异常的调用栈
e.printStackTrace();
}
System.out.println("after try");
}
}
输出结果为:
before
java.lang.ArrayIndexOutOfBoundsException: 100
at package9.Abnormal.main(Abnormal.java:8)
after try
一个程序如果出现了异常,并且程序员没有手动处理的话,异常就会被JVM来处理,JVM就会打印出现异常的调用栈及相关的异常信息,同时让程序终止运行了
我们也可以采用让程序员手动处理,手动处理的过程中,e.printStackTrace 也能打印出现异常的调用栈和相关的信息,同时程序还能继续的运行,我们也可以在catch内添加一个 System.exit(1); 来手动退出
关于异常的处理方式:
(1)异常的种类有很多, 我们要根据不同的业务场景来决定.
(2)对于比较严重的问题(例如和算钱相关的场景), 应该让程序直接崩溃, 防止造成更严重的后果
(3)对于不太严重的问题(大多数场景), 可以记录错误日志, 并通过监控报警程序及时通知程序猿
(4)对于可能会恢复的问题(和网络相关的场景), 可以尝试进行重试.
注意:
(1)程序员要保证非常清楚 try 中会抛出什么样种类的异常, catch 参数的类型要和 try 中抛出的异常相互匹配
如果不匹配的话, catch 不会生效,仍然是由 JVM 自己来处理
(2)try 语句块中抛出的异常可能会有很多种,这个时候我们可以采用多个 catch 来分别处理
示例:
public class Abnormal {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4};
try {
System.out.println("before");
arr = null;
System.out.println(arr[100]);
System.out.println("after");
} catch (ArrayIndexOutOfBoundsException e) {
//打印出异常的调用栈
System.out.println("这是个数组下标越界异常");
e.printStackTrace();
// System.exit(1);
} catch (NullPointerException e) {
System.out.println("这是个空指针异常");
e.printStackTrace();
}
System.out.println("after try");
}
}
(3)Exception 是常用的异常类的父类,各种常用异常都可以通过这个类来进行捕获,但是不太推荐使用
示例:
public class Abnormal {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4};
try {
System.out.println("before");
arr = null;
System.out.println(arr[100]);
System.out.println("after");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("after try");
}
}
不太建议使用,最好还是要针对不同的异常分别处理,因为在实际的工作当中这样的处理方式往往是不合理的
异常处理流程:
程序先执行 try 中的代码
如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.
如果找到匹配的异常类型, 就会执行 catch 中的代码
如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.
无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).
如果上层调用者也没有处理的了异常, 就继续向上传递.
一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止.
finall 的执行时机在方法执行 return 之前,如果 finally 由 return 就会影响到方法的最终结果,所以我们最终的建议是,不推荐将 return 放在 finally 语句之中
示例:
public class Abnormal {
public static int func() {
try {
int[] arr = {1, 2, 3, 4};
System.out.println("before");
System.out.println(arr[100]);
System.out.println("after");
return 10;
} catch (Exception e) {
e.printStackTrace();
} finally {
return 20;
}
}
public static void main(String[] args) {
System.out.println(func());
}
}
抛出异常 : throw
示例:
public static int divide(int x, int y) {
if (y == 0) {
throw new ArithmeticException("除数为0");
}
return x / y;
}
public static void main(String[] args) {
System.out.println(divide(10,0));
}
输出结果为:
Exception in thread “main” java.lang.ArithmeticException: 除数为0
at package9.Abnormal.divide(Abnormal.java:20)
at package9.Abnormal.main(Abnormal.java:25)