📅  最后修改于: 2020-04-04 07:10:40             🧑  作者: Mango
什么是异常
异常是不需要的或意外的事件,它在程序执行期间(即在运行时)发生,它破坏了程序指令的正常流程。
错误与异常
错误: 错误表示严重的问题,即合理的应用程序不应尝试捕获。
异常: 异常表示合理的应用程序可能尝试捕获的条件。
异常层次
所有异常和错误类型都是Throwable类的子类,Throwable类是层次结构的基类。一个分支以Exception为头。此类用于用户程序应捕获的异常条件。NullPointerException是此类异常的示例。Java运行时系统(JVM)使用另一个分支Error来指示与运行时环境本身(JRE)有关的错误。StackOverflowError是此类错误的示例。
JVM如何处理异常?
默认异常处理:无论何时在方法内部,如果发生异常,该方法都会创建一个称为“异常对象”的对象,并将其交给运行时系统(JVM)。异常对象包含异常的名称和描述,以及发生异常的程序的当前状态。创建异常对象并将其处理到运行时系统称为抛出异常。可能存在被调用以获取发生异常的方法的列表。该方法的有序列表称为“ 调用堆栈”。现在将发生以下过程。
Exception in thread "xxx" Name of Exception : Description
... ...... .. // Call Stack
请参见下图以了解调用堆栈的流程。
范例:
// Java程序展示异常如何被抛出
class ThrowsExecp{
public static void main(String args[]){
String str = null;
System.out.println(str.length());
}
}
输出:
Exception in thread "main" java.lang.NullPointerException
at ThrowsExecp.main(File.Java:8)
让我们看一个示例,该示例说明运行时系统如何在调用堆栈上搜索适当的异常处理代码:
// Java程序说明运行时系统如何在调用堆栈上搜索适当的异常处理代码
class ExceptionThrown
{
// 抛出异常(ArithmeticException).
// 合适的异常处理没有在此方法内找到
static int divideByZero(int a, int b){
// 如下会导致异常:ArithmeticException,除以零
int i = a/b;
return i;
}
// 运行时系统,寻找合适的异常处理,但是没有找到然后以与调用方法相反的顺序遍历调用堆栈
static int computeDivision(int a, int b) {
int res =0;
try
{
res = divideByZero(a,b);
}
// 不匹配:ArithmeticException
catch(NumberFormatException ex)
{
System.out.println("NumberFormatException发生");
}
return res;
}
// 这个方法内找到合适的异常处理
public static void main(String args[]){
int a = 1;
int b = 0;
try
{
int i = computeDivision(a,b);
}
// 匹配 ArithmeticException
catch(ArithmeticException ex)
{
// getMessage会打印异常(这里是 / by zero)
System.out.println(ex.getMessage());
}
}
}
输出:
/ by zero.
程序员如何处理异常
定制的异常处理: Java异常处理通过五个关键字进行管理:try,catch,throw,throws和finally。简而言之,这是它们的工作方式。您认为会引发异常的程序语句包含在try块中。如果try块中发生异常,则将引发该异常。您的代码可以捕获此异常(使用catch块)并以某种合理的方式处理它。系统生成的异常由Java运行时系统自动引发。要手动引发异常,请使用关键字throw。从方法抛出的任何异常都必须通过throws进行指定。条款。在try块完成之后绝对必须执行的所有代码都放在finally块中。
try-catch子句(自定义异常处理)
考虑下面的Java程序。
// Java程序,展示try-catch子句
class GFG {
public static void main (String[] args) {
// 尺寸=4的array.
int[] arr = new int[4];
// 这个声明抛出异常
int i = arr[4];
// 下面语句不会被执行
System.out.println("嗨,我要执行");
}
}
输出:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
at GFG.main(GFG.Java:9)
说明:在上面的示例中,数组的大小是定义的,即您只能访问索引0到3的元素。但是您尝试访问索引4的元素(错误),这就是它引发异常的原因。在这种情况下, JVM 异常终止程序。语句System.out.println(“嗨,我要执行”); 将永远不会执行。要执行它,我们必须使用try-catch处理异常。因此,为了继续程序的正常进行,我们需要try-catch子句。
如何使用try-catch子句
try {
// 你认为会抛出异常的代码
}
catch (ExceptionType1 exOb) {
// 对ExceptionType1的异常处理
}
catch (ExceptionType2 exOb) {
// 对ExceptionType2的异常处理
}
// 以下可选
finally {
// 在try代码块之后执行的code
}
要记住的要点: