当前位置:首页 > Java技术 > Java异常与异常处理简单使用

Java异常与异常处理简单使用

2022年11月08日 19:44:10Java技术7

  异常就是程序运行过程中阻止当前方法或作用域继续执行的问题;

  任何程序都不能保证完全正常运行,当发生异常时,需要我们去处理异常,特别是一些比较重要的场景,异常处理的逻辑也会比较复杂,比如:给用户提示、保存当前用户操作或改动、未完成的业务回滚、释放程序占用的资源等。

  在Java中,Throwable异常类是所有异常类的祖先,任何异常类都继承于Throwable类;

  Throwable类主要有两个子类:Error类、Exception类

  Error异常类是系统异常,比如:虚拟机错误(VirtualMachineError)、线程死锁(ThreadDeath)等,Error类异常一旦发生,程序将会崩溃

  Exception是开发中我们最常见的一般异常,这种异常原因可能是程序代码编写错误,环境问题,用户输入错误等异常

  Exception异常一般分为:运行时异常(RuntimeException)也称为非检查异常、检查异常;

  非检查异常常见的有:输出空指针时的异常,数组下标越界异常,类型转换异常,算术异常(比如0作为分母)等,运行时异常会由Java虚拟机自动捕获,自动抛出,一般是我们写的代码本身有问题,需要改进我们的代码来解决

  检查异常的原因有可能是:文件异常(不存在或者权限)、数据库连接异常、网络连接异常等,这种异常系统不会自动捕获,需要我们手动添加捕获处理的语句

  

  我们通常使用try-catch以及try-catch-finally代码块来处理异常

  try代码块中是可能发生异常的语句,当程序确实发生异常了,try块中程序会中止执行,并且抛出异常给catch块进行处理,catch根据需要去处理异常、记录错误日志等,看一个简单示例:

 1 import java.util.Scanner;
 2 
 3 public class Ceshi {
 4     public static void main(String[] args){
 5         try{
 6             System.out.println("请输入一个整数:");
 7             Scanner input = new Scanner(System.in);
 8             int a = input.nextInt();
 9             System.out.println("您输入的是:" + a);
10         }catch(Exception e){
11             System.out.println("输入异常");
12             e.printStackTrace();    //打印异常信息
13         }
14         System.out.println("程序执行结束");
15     }
16 }

这是一个最简单的异常处理,通过Scanner获取用户输入,当用户正确输入时程序正常执行,当然catch块不会被执行,但是用户如果输入的不是整数,那么就会抛出异常给catch块,可以利用printStackTrace()方法打印具体的异常,注意无论程序是否异常try-catch外的语句都会被正常执行,错误结果如下:

Java异常与异常处理简单使用 _ JavaClub全栈架构师技术笔记

根据结果可以看到我们输入字符串"3s"之后,抛出了异常并且提示输入异常,最后但是try-catch后面的语句正常执行,抛出的e.printStackTrace()会在最后被打印出来,可以看出来是Ceshi.java第就行发生了异常产生了终止,那么就是在a接收输入这一行语句中发生的异常,那么在这一行之后的所有try块中的语句便终止执行

另外如果try中的代码会抛出好几个类型的异常,那么我们需要多个catch块来处理,并且加上finally进行善后处理工作

 1 import java.util.Scanner;
 2 import java.util.InputMismatchException;
 3 import java.lang.ArithmeticException;
 4 public class Ceshi {
 5     public static void main(String[] args){
 6         Scanner input = new Scanner(System.in);
 7         try{
 8             System.out.println("请输入分子:");
 9             int a = input.nextInt();
10             System.out.println("您输入分母:");
11             int b = input.nextInt();
12             System.out.println("计算结果是:" + a*1.0/b);
13         }catch(InputMismatchException e){
14             System.out.println("请输入整数");
15             e.printStackTrace();    //打印异常信息
16         }catch(ArithmeticException e){
17             System.out.println("分母不能为0");
18             e.printStackTrace();    //打印异常信息
19         }catch(Exception e){
20             System.out.println("其他未知异常");
21             e.printStackTrace();
22         }finally{
23             input.close();
24         }
25         System.out.println("程序执行结束");
26     }
27 }

以上的处理就比较合理了,首先保证输入是整数,如果都是整数那么分母为0也会抛出异常,最后如果还有我们考虑不到的异常,那么就通过Exception父类抛出异常,catch异常块从上到下一般是是由小到大或者由子类到父类的异常类抛出,就是从作用范围来说从细节到整体,Exception异常类抛出必须放在最后面,这样能抛出我们开发中遇到的所有异常,另外finally块建议带上,当遇到异常时,他可以释放前面还未操作的系统资源,比如例子中的关闭输入,这样能提高程序的健壮性,如果try和catch中有返回值,那么finally中的语句会在try和catch语句块中的return返回值返回到调用者之前,获得该返回值,我们可以在程序中输出他们,但是放在try-catch-finally外返回值时在finally是无法获取到的,只能获取前面的变量值

  Java中方法异常抛出,因为很多代码我们会写到方法中,为了便于管理,我们可以在专门的方法中处理异常,所以我们可以将方法中的异常向上抛出,可以写一个方法来简单抛出异常,代码如下:

1 public void divide(int a,int b) throws Exception {
2     if(b == 0){
3         throw new Exception("除数不能为零!");
4     }else{
5         System.out.println("结果为:" + a*1.0/b);
6     }
7 }

 

当该方法被调用时,那么如果发生异常,异常将抛出到调用的语句块中,我们可以在调用的时候进行处理,比如:

1 public void complte() {
2     try{
3         divide(5,0);    //此时发生异常,调用方法将异常抛出到这里
4     }catch(Exception e){
5         System.out.println(e.getMessage());    //此处捕获异常,将方法中定义的异常信息抛出
6     }
7 }

这样就把方法中的异常抛出并进行了处理,另外我们还可以不在complte方法中抛出,还可以向上抛出,由上面调用该方法时抛出异常,代码如下:

public void complte() throws Exception {
    /**
     * 省略方法中的代码
     */
    divide(5,0);    //将里面的异常抛出到调用complte方法的位置
}

这样的话异常继续向上抛出,最终还是按照第二段代码的方式来处理异常,所以用throws关键字声明此方法向上抛出异常,用throw关键字来抛出异常

 

  自定义异常

  除了利用系统的异常我们还可以自定义异常,以便适应我们情景的需要,简单定义个异常类:

 1 public class CeshiException extends Exception {
 2 
 3     public CeshiException(){
 4         
 5     }
 6     
 7     public CeshiException(String message){
 8         super(message);
 9     }
10 }

注意,自定义异常类必须继承于Exception异常类,里面定义了一个有参数的构造方法来自定义异常信息,无参的构造方法是为了实例化类时,默认不会发生错误,那么我们可以在方法中具体来使用这个自定义异常类了:

 1 public class ChainTest {
 2 
 3     /**
 4      * test1():抛出自定义异常
 5      * test2():调用test1(),捕获自定义异常,并且包装成运行时异常,抛出新异常
 6      * main方法中,调用test2(),尝试捕获test2()方法抛出的异常
 7      */
 8     public static void main(String[] args) {
 9         ChainTest ct = new ChainTest();
10         try{
11             ct.test2();
12         }catch(Exception e){
13             e.printStackTrace();
14         }
15     }
16 
17     public void test1() throws CeshiException{
18         throw new CeshiException("原始自定义异常抛出");
19     }
20     
21     public void test2(){
22         try {
23             test1();
24         } catch (CeshiException e) {
25             // TODO Auto-generated catch block
26             RuntimeException newExc = 
27                 new RuntimeException("抛出新运行时异常");
28             newExc.initCause(e);    //引用原始异常方法,异常链
29             throw newExc;
30         }
31     }
32 }

根据代码可以看出,main方法调用test2方法并捕获test2方法抛出的异常,而test2方法中运行test1并捕获test1方法中抛出的自定义异常,并且自己也抛出一个新的运行时异常抛出到main方法中,而test1方法通过声明自定义异常类实现了抛出自定义异常类中的异常方法,将异常抛出到test2中,这样就好比一连串的异常抛出和异常处理,同时结合了自定义异常,这样就形成了一个小型的异常链,就好像链式反应一样去抛出异常

 

  最后,总结一下,通过try-catch来处理异常,并不能避免错误的存在性,而是尽量提高程序的健壮性,减小程序错误而带来的安全风险和损失,我们不能一味的用try-catch来屏蔽错误,我们应该采用合理的逻辑算法来解决程序设计的不足,try-catch只是一个作为辅助使用,不可以过分依赖;

  在多重catch块之后,最好加个catch(Exception e){}来处理其他可能会被遗漏的未知的异常,对于不太确定的异常,可以加上try-catch来处理潜在的风险;

  对于异常一定要尽量去处理,千万不要只是简单地使用e.printStackTrace();来打印错误信息,这样就失去了异常处理的意义;

  具体如何处理异常,应该根据不同的业务需求和异常类型来确定;

  最后要善于在try-catch块后面添加finally语句块,释放系统资源的占用,比如网络连接、数据库连接、文件关闭等;

  什么时候怎么使用异常,还需要自己以后在开发中慢慢的熟悉

 

作者:小得盈满
来源链接:https://www.cnblogs.com/freeweb/p/4823815.html

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/java/68544.html

分享给朋友:

“Java异常与异常处理简单使用” 的相关文章

二分法(折半查找)的运用之java实现猜数字游戏

让计算机输入一个数 然后用户进行猜数游戏 一般而言,七次会猜对,如果猜不对,那么就是你的方法不对 在这儿涉及到的一个算法就是二分法 ***二分法查找,***也称为折半法,是一种在有序数组中查找特定元素的搜索算法。二分法查找的思路如下: (1)首先,从数组...

Java实现ModbusTCP通信

Java实现ModbusTCP通信

使用ModbusTCP实现和硬件设备通信 有问题可以私信和评论,看到会回复。 一个项目,需要用Java实现使用ModbusTCP和硬件设备通信 视频地址:https://www.bilibili.com/video/BV1cz4y1R7cg...

java提高篇(二五)

java提高篇(二五)

      在java中与有两个类都提供了一个多种用途的hashTable机制,他们都可以将可以key和value结合起来构成键值对通过put(key,value)方法保存起来,然后通过get(key)方法获取相对应的value值。一个...

Java 基础之详解 Java IO

Java 基础之详解 Java IO

Java IO 基本概念 Java IO:即 Java 输入 / 输出系统。 区分 Java 的输入和输出:把自己当成程序, 当你从外边读数据到自己这里就用输入(InputStream/Reader), 向外边写数据就用输出(OutputStream/Writer)。...

深入理解Java类加载

深入理解Java类加载

本文目的: 1. 深入理解Java类加载机制; 2. 理解各个类加载器特别是线程上下文加载器。 虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型,这就是虚拟机的类加载机制。 本文将深入探究Java的类...

java中的内存模型

java中的内存模型

概述 Java平台自动集成了线程以及多处理器技术,这种集成程度比Java以前诞生的计算机语言要厉害很多,该语言针对多种异构平台的平台独立性而使用的多线程技术支持也是具有开拓性的一面,有时候在开发Java同步和线程安全要求很严格的程序时,往往容易混淆的一个概念就是内存模型。究竟什么...

JavaWeb 并发:FOR UPDATE 实战,监测并解决。

JavaWeb 并发:FOR UPDATE 实战,监测并解决。

Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket   一、前言 针对并发,老生常谈了。目前一个通用的做法有两种:锁机制:1.悲观锁;2.乐观锁。 但是这篇我主要用于记录我...

[biomaRt] Query ERROR: caught BioMart::Exception::Usage: Attributes from multiple attribute pages are not allowed

[biomaRt] Query ERROR: caught BioMart::Exception::Usage: Attributes from multiple attribute pages are not allowed

正文 Query ERROR: caught BioMart::Exception::Usage: Attributes from multiple attribute pages are not allowed 就如报错所说, 来源于多个attribute pages...

Java 容器 & 泛型:六、容器讲到为什么要使用泛型

Java 容器 & 泛型:六、容器讲到为什么要使用泛型

Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket     ArrayList是集合类中无处不在的,泛型也是,泛型对集合类尤其有用。但是为啥要使用泛型?理解好了这个问题可以帮助理...

2.Java中Exception和Error的区别

2.Java中Exception和Error的区别

Exception和Error都是继承了Throwable类,在Java中只有Throwable类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型 Error是指在正常情况下,不大可能出现的情况,绝大部分的Error都会导致程序(比...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。