从零开始的Java开发1-5-1 异常:分类异常处理try-catch-finally多重catchfinally与returnthrowsthrow关键字自定义异常类异常链
Posted karshey
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从零开始的Java开发1-5-1 异常:分类异常处理try-catch-finally多重catchfinally与returnthrowsthrow关键字自定义异常类异常链相关的知识,希望对你有一定的参考价值。
文章目录
什么是异常
- 异常就是程序的错误。
- 错误在我们编写程序的过程中会经常发生,包括编译期间和运行期间的错误。
- 在程序运行过程中,意外发生的情况,背离我们程序本身意图的表现,都可以理解为异常。
举个例子:这些都算是运行的错误——在编译时没有错误提示。
异常分类
在Java中,用Throwable
和它的子类对异常进行描述。
Throwable
分为Error
和Exception
:
Error
:是程序中无法处理的错误,表示运行应用程序中较严重的问题——大多数错误与代码编写者执行的操作无关,主要是代码运行是Java虚拟机出现的问题,如:虚拟机错误VirtualMachineError
,内存溢出OutOfMemoryError
,线程死锁ThreadDeath
Exception
:是程序本身可以处理的异常。异常处理通常指针对这种异常的处理。包括:非检查异常Unchecked Exception
,检查异常Checked Exception
关于Error
:它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况,对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况
关于Unchecked Exception
:编译器不要求强制处理的异常,包含RuntimeException
以及它的相关子类。如:
- 空指针异常
- 数组下标越界异常
- 算数异常
- 类型转换异常
关于Checked Exception
:编译器要求在代码中处理的异常。是RuntimeException
以及它的相关子类之外的异常。
思维导图
异常处理
在Java应用程序中,异常处理机制分为:
- 抛出异常
- 捕捉异常
关于捕获异常:
对于运行时异常、错误或可查异常,Java技术所要求的异常处理方式有所不同。
Java规定:
- 对于可查异常必须捕捉、或者声明抛出
- 允许忽略不可查的
RuntimeException
(含子类)和Error
(含子类)
关于关键字:try
、catch
、finally
、throw
、throws
try-catch-finally
try
:用于捕获异常
catch
:用于处理捕获到的异常
finally
:无论是否发生异常,代码总能执行
**try块后可接零个或者多个catch块,如果没有catch块,必须跟一个finally块。**简言之,try必须跟catch或finally组合使用,不允许单独存在。
举例:要求:定义两个整,接收键盘用户输入,输出两数之商。
代码:
public class TryDemoOne
public static void main(String[] args)
// TODO Auto-generated method stub
// 要求:定义两个整,接收键盘用户输入,输出两数之商。
System.out.println("请输入两个整数:");
Scanner input = new Scanner(System.in);
int one = input.nextInt(), two = input.nextInt();
System.out.println("商为" + one / two);
奇葩输入1:12 0
则输出:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ExceptionProj/com.test.TryDemoOne.main(TryDemoOne.java:13)
奇葩输入2:12 a
则输出:
Exception in thread "main" java.util.InputMismatchException
at java.base/java.util.Scanner.throwFor(Scanner.java:939)
at java.base/java.util.Scanner.next(Scanner.java:1594)
at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
at ExceptionProj/com.test.TryDemoOne.main(TryDemoOne.java:12)
接下来我们使用try-catch
结构处理上述异常。
若有异常,catch会捕获它,然后输出其代码块内的内容;否则完成try内的操作。
public class TryDemoOne
public static void main(String[] args)
// TODO Auto-generated method stub
// 要求:定义两个整,接收键盘用户输入,输出两数之商。
try
System.out.println("请输入两个整数:");
Scanner input = new Scanner(System.in);
int one = input.nextInt(), two = input.nextInt();
System.out.println("商为" + one / two);
catch (Exception e)
System.out.println("程序出错啦!");
System.out.println("运算结束");
输入:12 a
输出:
程序出错啦!
运算结束
输入:12 0
输出:
程序出错啦!
运算结束
如果我们想知道错误的类型和位置,可以在catch
中添加语句:e.printStackTrace();
如:
public class TryDemoOne
public static void main(String[] args)
// TODO Auto-generated method stub
// 要求:定义两个整,接收键盘用户输入,输出两数之商。
try
System.out.println("请输入两个整数:");
Scanner input = new Scanner(System.in);
int one = input.nextInt(), two = input.nextInt();
System.out.println("商为" + one / two);
catch (Exception e)
e.printStackTrace();
System.out.println("程序出错啦!");
System.out.println("运算结束");
那么输入12 0
时,会输出:
java.lang.ArithmeticException: / by zero
程序出错啦!
at ExceptionProj/com.test.TryDemoOne.main(TryDemoOne.java:14)
运算结束
ps:e.printStackTrace();
的错误信息的输出位置相对随机,不用计较。
我们该怎么看异常信息呢? 以
at java.base/java.util.Scanner.throwFor(Scanner.java:939)
at java.base/java.util.Scanner.next(Scanner.java:1594)
at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
at ExceptionProj/com.test.TryDemoOne.main(TryDemoOne.java:13)
为例,这是输入12 a
的异常信息。
我们要从下往上看。
最后一行at ExceptionProj/com.test.TryDemoOne.main(TryDemoOne.java:13)
表示:异常发生的最外层的表示是在TryDemoOne.java
文件的第13行:
在这个位置它调用了Scanner.nextInt
方法,在Scanner.java:2212
,我们点击它,则跳转到Scanner.class
:
而这个位置调用了nextInt(defaultRadix)
,其实就是在Scanner.nextInt(Scanner.java:2258)
,点击它则跳转到:
到这里我们可以看到integerPattern()
,大概能猜出来这是一个整数转换的方法,而a肯定不能转化为整数,所以会跳转到Scanner.next(Scanner.java:1594)
,即:throwFor()
,异常抛出。
异常抛出的具体代码在Scanner.throwFor(Scanner.java:939)
,即:
所以,我们这里的异常是:InputMismatchException
,会被catch
所捕获。
这就是try-catch
产生异常、捕获异常的整体流程。
关于finally
:我们如果想要某个语句不管是否产生异常都一定要执行,可以在这个语句外套一个finally
,如:
public class TryDemoOne
public static void main(String[] args)
// TODO Auto-generated method stub
// 要求:定义两个整,接收键盘用户输入,输出两数之商。
try
System.out.println("请输入两个整数:");
Scanner input = new Scanner(System.in);
int one = input.nextInt(), two = input.nextInt();
System.out.println("商为" + one / two);
catch (Exception e)
e.printStackTrace();
System.out.println("程序出错啦!");
finally
System.out.println("运算结束");
使用多重catch结构处理异常
如果针对不同的异常,有不同的处理方式,该怎么解决呢?
答:用多重catch解决
ps:
- 多重
catch
时不能出现同类型异常 - 安全起见,多重
catch
块的最后一个块中异常为Exception
(不能放第一个,会报错)
代码如下:
public static void main(String[] args)
// TODO Auto-generated method stub
// 要求:定义两个整,接收键盘用户输入,输出两数之商。
try
System.out.println("请输入两个整数:");
Scanner input = new Scanner(System.in);
int one = input.nextInt(), two = input.nextInt();
System.out.println("商为" + one / two);
catch (ArithmeticException e)
System.out.println("除数不能为0");
e.printStackTrace();
catch (InputMismatchException e)
System.out.println("请输入整数");
e.printStackTrace();
catch (Exception e)
System.out.println("其他异常");
e.printStackTrace();
finally
System.out.println("运算结束");
测试输入:12 0
输出:
除数不能为0
java.lang.ArithmeticException: / by zero
运算结束
at ExceptionProj/com.test.TryDemoOne.main(TryDemoOne.java:14)
测试输入:12 a
请输入整数
java.util.InputMismatchException
运算结束
at java.base/java.util.Scanner.throwFor(Scanner.java:939)
at java.base/java.util.Scanner.next(Scanner.java:1594)
at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
at ExceptionProj/com.test.TryDemoOne.main(TryDemoOne.java:13)
终止finally执行的方法
catch
和finally
不能脱离try
独自出现。
一般情况下,不管finally一定会执行,有没有终止finally执行的方法呢?
答:有。System.exit(1)
;
则若catch的代码改成:
catch (ArithmeticException e)
System.exit(1);
System.out.println("除数不能为0");
e.printStackTrace();
那么他会在System.exit(1);
时终止程序的执行,就不会允许到finally了。
return关键字在异常处理中的作用
类如下:
public class Test
public static void main(String[] args)
int res=test();
System.out.println("商为"+res);
public static int test()
try
System.out.println("请输入两个整数:");
Scanner input = new Scanner(System.in);
int one = input.nextInt(), two = input.nextInt();
return one/two;
catch (ArithmeticException e)
System.out.println("除数不能为0");
return 0;
catch (Exception e)
System.out.println("其他异常");
e.printStackTrace();
finally
System.out.println("运算结束");
return -10000;
测试输入为:2 1
输出:
运算结束
商为-10000
输入为:2 0
输出:
除数不能为0
运算结束
商为-10000
由此可见,在try-catch-finally中,三个语句都有return的情况下,永远都是返回finally中的return
也就是说,从语法的角度上finally块中带return是没问题的,但从逻辑的角度上,finally块中的return是一定会被返回的——这也就是为什么finally中有return就会有Warning:
如果把finally中的return删去,即:
public static int test()
try
System.out.println("请输入两个整数:");
Scanner input = new Scanner(System.in);
int one = input.nextInt(), two = input.nextInt();
return one/two;
catch (ArithmeticException e)
System.out.println("除数不能为0");
return 0;
catch (Exception e)
System.out.println("其他异常");
e.printStackTrace();
return 0;
finally
System.out.println("运算结束");
再测试一下:
输入:2 1
输出:
运算结束
商为2
输入:2 0
输出:
除数不能为0
运算结束
商为0
这就正确了。
使用throws声明异常类型
可以通过throws
声明将要抛出何种类型的异常,通过throw
将产生的异常抛出。如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法声明处用throws
子句来声明抛出异常。
throws
语句用在方法定义时声明该方法要抛出的异常类型。
public void method() throws Exception 1,Exception 2
//可能产生异常的代码
当方法抛出异常列表中的异常时,方法将不对这些类型及其子类作处理,而抛向调用该方法的方法,由他去处理。
举个例子:
测试类代码如下:
public class TryDemo3
public static void main(String[] args)
try
int res = test();
System.out.println("商为" + res);
catch (ArithmeticException e)
// TODO Auto-generated catch block
System.out.println("除数不允许为0");
e.printStackTrace();
//表示这个函数可能会抛出ArithmeticException这样的异常
public static int test() throws ArithmeticException
System.out.println("请输入两个整数:");
Scanner input = new Scanner(System.in);
int one = input.nextInt(), two = input.nextInt();
System.out.println("运算结束");
return one / two;
测试输入1:2 1
输出:
运算结束
商为2
测试输入2:2 0
输出:
运算结束
java.lang.ArithmeticException: / by zero
除数不允许为0
at ExceptionProj/com.test.TryDemo3.test(TryDemo3.java:26)
at ExceptionProj/com.test.TryDemo3.main(TryDemo3.java:10)
这段代码能处理别的异常吗?答案是不可以。
测试输入3:2 a
输出:这个异常是虚拟机在处理。
Exception in thread "main" java.util.InputMismatchException
at java.base/java.util.Scanner.throwFor(Scanner.java:939)
at java.base/java.util.Scanner.next(Scanner.java:1594)
at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
at ExceptionProj/com.test.TryDemo3.test以上是关于从零开始的Java开发1-5-1 异常:分类异常处理try-catch-finally多重catchfinally与returnthrowsthrow关键字自定义异常类异常链的主要内容,如果未能解决你的问题,请参考以下文章