Java异常处理之捕获异常

简介: 笔记

一、try-catch语句


捕获异常是通过try-catch语句实现的,最基本try-catch语句语法如下:

try{ //可能会发生异常的语句
} catch(Throwable e){ //处理异常e
}

1.try代码块

try代码块中应该包含执行过程中可能会发生异常的语句。一条语句是否有可能发生异常,这要 看语句中调用的方法。

如下:

public Date parse(String source) throws ParseException

方法后面的throws ParseException说明:当调用parse()方法时有可以能产生ParseException异常。

提示:静态方法、实例方法和构造方法都可以声明抛出异常,凡是抛出异常的方法都可以 通过try-catch进行捕获,当然运行时异常可以不捕获。一个方法声明抛出什么样的异常需要 查询API文档。


2.catch代码块

每个try代码块可以伴随一个或多个catch代码块,用于处理try代码块中所可能发生的多种异常。 catch(Throwable e)语句中的e是捕获异常对象,e必须是Throwable的子类,异常对象e的作用域在 该catch代码块中。

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
//try-catch代码块
public class HelloWorld {
    public static void main(String[] args) {
        Date date = readDate();
        System.out.println("日期="+date);
    }
//    定义了一个静态方法来将字符串解析成日期
    public static Date readDate(){
        try {
            String str = "2020-2-9";
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
//            从字符串中解析日期,解析方法可能有发生ParseException异常
            Date date = dateFormat.parse(str);
            return date;
        } catch (ParseException e) {
            System.out.println("处理ParseException异常");
//            e.printStackTrace()是打印异常堆栈跟踪信息
            e.printStackTrace();
        }
        return null;
    }
}

运行结果:

日期=Sun Feb 09 00:00:00 CST 2020
Process finished with exit code 0


二、多catch代码块


如果try代码块中有很多语句会发生异常,而且发生的异常种类又很多。那么可以在try后面跟有多个catch代码块。多catch代码块语法如下:

try{ //可能会发生异常的语句
} catch(Throwable e){ //处理异常e
} catch(Throwable e){ //处理异常e
} catch(Throwable e){ //处理异常e
}

注意:在多个catch代码情况下,当一个catch代码块捕获到一个异常时,其他的catch代码块就不再进行匹配。当捕获的多个异常类之间存在父子关系时,捕获异常顺序与catch代码块的顺序有关。一般 先捕获子类,后捕获父类,否则子类捕获不到。

代码如下:

import java.io.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
//多catch代码块
public class HelloWorld1 {
    public static void main(String[] args) {
        Date date = readDate();
        System.out.println("日期="+date);
    }
    public static Date readDate(){
        FileInputStream readfile = null;
        InputStreamReader ir = null;
        BufferedReader in = null;
        try {
//            调用FileInputStream()构造方法可能会发生FileNotFoundException异常
            readfile = new FileInputStream("readme.txt");
            ir = new InputStreamReader(readfile);
            in = new BufferedReader(ir);
//            读取文件中的一行数据, 调用BufferedReader输入流的readLine()方法可能会发生IOException异常
            String str = in.readLine();
            if (str == null){
                return null;
            }
//            调用SimpleDateFormat()方法可能会发生ParseException异常
            DateFormat df  = new SimpleDateFormat("yyyy-MM-dd");
            java.util.Date date = df.parse(str);
            return date;
//          应该先捕获FileNotFoundException异常后捕获IOException(先捕获子类异常)
        } catch (FileNotFoundException e) {
            System.out.println("处理FileNotFoundException");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("处理IOException");
            e.printStackTrace();
        } catch (ParseException e) {
            System.out.println("处理ParseException");
            e.printStackTrace();
        }
        return null;
    }
}

运行结果:

处理FileNotFoundException
日期=null
java.io.FileNotFoundException: readme.txt (No such file or directory)
  at java.io.FileInputStream.open0(Native Method)
  at java.io.FileInputStream.open(FileInputStream.java:195)
  at java.io.FileInputStream.<init>(FileInputStream.java:138)
  at java.io.FileInputStream.<init>(FileInputStream.java:93)
  at 异常处理类.捕获异常.HelloWorld1.readDate(HelloWorld1.java:29)
  at 异常处理类.捕获异常.HelloWorld1.main(HelloWorld1.java:19)

如果将FileNotFoundException和IOException捕获顺序调换,代码如下:

try{ 
//可能会发生异常的语句
} catch (IOException e) { 
// IOException异常处理
} catch (FileNotFoundException e) { 
// FileNotFoundException异常处理
}

那么第二个catch代码块永远不会进入,FileNotFoundException异常处理永远不会执行。 由于上述代码ParseException异常与IOException和FileNotFoundException异常没有父子关系,捕获ParseException异常位置可以随意放置。


三、try-catch语句嵌套


代码如下:

import java.io.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
//try-catch语句嵌套
public class HelloWorld2 {
    public static void main(String[] args) {
        Date date = redaDate();
        System.out.println("日期="+date);
    }
    public static Date redaDate(){
        FileInputStream readfile = null;
        InputStreamReader ir = null;
        BufferedReader in = null;
        try {
//            调用FileInputStream()构造方法可能会发生FileNotFoundException异常,如果外层出现异常先捕获外层异常
            readfile = new FileInputStream("readme.txt");
            ir = new InputStreamReader(readfile);
            in = new BufferedReader(ir);
            try {
//            读取文件中的一行数据, 调用BufferedReader输入流的readLine()方法可能会发生IOException异常
                String str = in.readLine();
                if(str == null){
                    return null;
                }
//                调用SimpleDateFormat()方法可能会发生ParseException异常
                DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                Date date = dateFormat.parse(str);
                return date;
            } catch (ParseException e) {
                System.out.println("处理ParseException");
                e.printStackTrace();
            } catch (IOException e) {
                System.out.println("处理IOException");
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            System.out.println("处理FileNotFoundException");
            e.printStackTrace();
        }
        return null;
    }
}

总结:程序执行时外层捕获到异常,其他的catch代码块就不再进行匹配。若外层没有捕获到异常则捕获内层异常,程序执行时内层如果会发生异常,首先由内层catch进行捕获,如果捕获不到,则由外层catch捕获。


四、多重捕获


1.为什么使用多重捕获

多catch代码块客观上提高了程序的健壮性,但是程序代码量大大增加。如果有些异常虽然种类不同,但捕获之后的处理是相同的,看如下代码。

try{ 
//可能会发生异常的语句
} catch (FileNotFoundException e) { 
//调用方法methodA处理
} catch (IOException e) { 
//调用方法methodA处理
} catch (ParseException e) {
//调用方法methodA处理
}


2.如何使用多重捕获

Java 7推出了多重捕获(multi-catch)技术,可以帮助解决此类问题,上述代码修改如下:

try{ 
//可能会发生异常的语句
} catch (IOException | ParseException e) { 
//调用方法methodA处理
}

在catch中多重捕获异常用“|”运算符连接起来。

注意 :什么不写成FileNotFoundException | IOException | ParseException 呢?这是因 为由于FileNotFoundException属于IOException异常,IOException异常可以捕获它的所有子类异常了。





相关文章
|
4天前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
45 14
|
7天前
|
缓存 Java 应用服务中间件
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
35 5
|
30天前
|
Java 数据库连接 数据处理
探究Java异常处理【保姆级教程】
Java 异常处理是确保程序稳健运行的关键机制。它通过捕获和处理运行时错误,避免程序崩溃。Java 的异常体系以 `Throwable` 为基础,分为 `Error` 和 `Exception`。前者表示严重错误,后者可细分为受检和非受检异常。常见的异常处理方式包括 `try-catch-finally`、`throws` 和 `throw` 关键字。此外,还可以自定义异常类以满足特定需求。最佳实践包括捕获具体异常、合理使用 `finally` 块和谨慎抛出异常。掌握这些技巧能显著提升程序的健壮性和可靠性。
47 4
|
2月前
|
Java API 开发者
深入理解Java中的异常处理机制
本文探讨了Java编程语言中异常处理的核心概念,包括异常类型、异常捕获与抛出、以及最佳实践。通过分析常见的异常场景和处理策略,旨在帮助开发者更好地理解和运用异常处理机制,提高代码的健壮性和可维护性。文章不仅涵盖了基本的try-catch结构,还深入讨论了自定义异常的创建与使用,以及finally块的重要性和应用。此外,还将介绍一些高级技巧,如多异常捕获和嵌套异常处理,为读者提供全面的技术指导。
115 0
|
2月前
|
Java
Java 异常处理:11 个异常处理最佳实践
本文深入探讨了Java异常处理的最佳实践,包括早抛出晚捕获、只捕获可处理异常、不忽略异常、抛出具体异常、正确包装异常、记录或抛出异常但不同时执行、不在finally中抛出异常、避免用异常控制流程、使用模板方法减少重复代码、抛出与方法相关的异常及异常处理后清理资源等内容,旨在提升代码质量和可维护性。
173 3
|
2月前
|
Java 程序员
深入理解Java异常处理机制
Java的异常处理是编程中的一块基石,它不仅保障了代码的健壮性,还提升了程序的可读性和可维护性。本文将深入浅出地探讨Java异常处理的核心概念、分类、处理策略以及最佳实践,旨在帮助读者建立正确的异常处理观念,提升编程效率和质量。
150 1
|
2月前
|
Java 开发者 UED
深入探索Java中的异常处理机制##
本文将带你深入了解Java语言中的异常处理机制,包括异常的分类、异常的捕获与处理、自定义异常的创建以及最佳实践。通过具体实例和代码演示,帮助你更好地理解和运用Java中的异常处理,提高程序的健壮性和可维护性。 ##
74 2
|
2月前
|
Java 开发者
Java 中的异常处理:不仅仅是 try-catch
在Java的世界里,异常处理是代码的守护神,它保护着程序不会因为意外错误而崩溃。但异常处理远不止try-catch那么简单。本文将深入探讨Java的异常处理机制,从基本的try-catch到更复杂的自定义异常和finally块的使用,带你理解如何在Java中优雅地处理错误。
66 1
|
7天前
|
安全 Java 程序员
Java 面试必问!线程构造方法和静态块的执行线程到底是谁?
大家好,我是小米。今天聊聊Java多线程面试题:线程类的构造方法和静态块是由哪个线程调用的?构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节有助于掌握Java多线程机制。下期再见! 简介: 本文通过一个常见的Java多线程面试题,详细讲解了线程类的构造方法和静态块是由哪个线程调用的。构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节对掌握Java多线程编程至关重要。
38 13
|
8天前
|
安全 Java 开发者
【JAVA】封装多线程原理
Java 中的多线程封装旨在简化使用、提高安全性和增强可维护性。通过抽象和隐藏底层细节,提供简洁接口。常见封装方式包括基于 Runnable 和 Callable 接口的任务封装,以及线程池的封装。Runnable 适用于无返回值任务,Callable 支持有返回值任务。线程池(如 ExecutorService)则用于管理和复用线程,减少性能开销。示例代码展示了如何实现这些封装,使多线程编程更加高效和安全。

热门文章

最新文章