Java入门系列-20-异常

简介:

为什么要进行异常处理

下面这段代码能否正常执行

public class DemoCalc {
    public static void main(String[] args) {
        int a=0;
        int b=0;
        int c=a/b;
        System.out.println("运算结果为:"+c);
    }
}

结果是我们在控制台中看到一段错误提示,那是因为除数不能为0。异常就是在程序运行过程中发生的不正常事件,会中断运行的程序

Java 使用了异常处理机制为程序提供了错误处理的能力,在程序中预先设置好对付异常的处理办法,待程序发生异常时对异常进行处理,处理完毕后,程序便可以继续运行。

下面来看一下Java中是如何进行异常处理的

如何进行异常处理

Java 的异常处理是通过5个关键字实现的:try、catch、finally、throw、throws

关键字 作用
try 执行可能产生异常的代码
catch 捕获异常
finally 无论是否发生异常,代码总能执行
throws 声明方法要抛出的异常
throw 手动抛出异常

常见异常及异常分类

Throwable 是Java 中所有错误和异常的父类

Error类:Throwable的子类,仅靠程序本身无法恢复的严重的错误。

Exception类:Throwable的子类,由Java应用程序抛出和处理的非严重错误

RuntimeException类:Exception的子类,运行时异常,不要求程序必须做出处理。

Checked异常:Exception的子类,程序必须处理该类异常。

常见异常类型

异常类型 说明
Exception 异常层次结构的父类
ArithmeticException 算数错误情形,如以零作除数
ArrayIndexOutOfBoundsException 数组下标越界
NullPointerException 尝试访问null对象成员
ClassNotFoundException 不能加载所需的类
IllegalArgumentException 方法接收到非法参数
ClassCastException 对象强制类型转换出错
NumberFormatException 数字格式转换异常,如把"abc"转换成数字

try-catch

语法:

public void method(){
    try{
        //代码段1
        //可能产生异常的代码段
        //代码段2
    }catch(异常类型 ex){
        //对异常进行处理的代码段
    }
    //代码段
}

try-catch块捕获异常有三种情况:

1、try块中没有任何异常,try中正常,catch不会执行,正常执行try-catch后的代码。

2、try块中可能发生异常的代码段发生异常,代码段2不会执行,而是执行catch中异常处理的代码,正常执行try-catch后的代码。

catch中异常类型的printStackTrace() 方法能进行堆栈跟踪显示出程序运行到当前类的执行流程,异常堆栈信息中包含了异常的类型及异常出现的位置。

3、异常类型不匹配,程序将中断。比如try产生的异常为ArithmeticException,catch却用了 ClassCastException。

在控制台中接收数字做除法运算

import java.util.Scanner;

public class DemoInput {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        try{
            System.out.println("请输入被除数(整数):");
            int a=input.nextInt();
            System.out.println("请输入除数(整数):");
            int b=input.nextInt();
            int c=a/b;
            System.out.println("结果:"+c);
        }catch(Exception ex) {
            ex.printStackTrace();
        }
        System.out.println("程序结束");
    }
}

try-catch-finally

语法:

public void method(){
    try{
        //可能会发生异常的代码
    }catch(异常类型 ex){
        //异常处理
    }finally{
        //无论如何都要执行的代码
    }
}

finally块:是否发生异常都执行

finllay块不执行的唯一情况:之前的代码中执行了 System.exit(1); 退出虚拟机

try-catch-finally的使用

import java.io.FileNotFoundException;
import java.util.Scanner;

public class DemoInput {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        try{
            System.out.println("请输入被除数(整数):");
            int a=input.nextInt();
            System.out.println("请输入除数(整数):");
            int b=input.nextInt();
            int c=a/b;
            System.out.println("结果:"+c);
        }catch(Exception ex) {
            ex.printStackTrace();
        }finally {
            System.out.println("感谢您的使用");
        }
        System.out.println("程序结束");
    }
}

如果在try块或catch块中有return语句,finally是否还会执行?运行下面代码断点调试观察结果。

public class TestReturn {

    public static void main(String[] args) {
        try {
            int a=1+1;
            System.out.println("try执行");
            return;
        } catch (Exception e) {
            System.out.println("catch执行");
        }finally {
            System.out.println("finally执行");
        }
    }
}

try块或catch块中可以有return语句,如果有return语句会先执行finally最后再执行return。

多重catch

try块中可能会发生多种异常,如果要不同的异常进行不同的处理,需要使用多重catch进行处理。

语法:

public void method(){
    try{
        //可能发生异常的代码段
    }catch(异常类型1 e){
        //对异常类型1进行的处理的代码段
    }catch(异常类型2 e){
        //对异常类型2进行的处理的代码段
    }catch(异常类型n e){
        //对异常类型n进行的处理的代码段
    }
}

当try块中发生异常后,会逐个与catch中的异常类型进行匹配,匹配成功后,进入对应的catch进行异常处理,处理完成后不再进入其他catch,程序继续执行。

排列catch语句的顺序是:先子类后父类

发生异常时按顺序逐个匹配

只执行第一个与异常类型匹配的catch语句

将之前的代码 DemoInput.java 改造成多重catch

import java.io.FileNotFoundException;
import java.util.InputMismatchException;
import java.util.Scanner;

public class DemoInput {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        try{
            System.out.println("请输入被除数(整数):");
            int a=input.nextInt();
            System.out.println("请输入除数(整数):");
            int b=input.nextInt();
            int c=a/b;
            System.out.println("结果:"+c);
        }catch(InputMismatchException e) {
            System.out.println("输入的数有误!");
        }catch(ArithmeticException e) {
            System.out.println("除数不能为0");
        }catch(Exception ex) {
            System.out.println("发生未知异常");
        }finally {
            System.out.println("感谢您的使用");
        }
        System.out.println("程序结束");
    }
}

声明异常 throws

如果一个方法体内抛出了异常如何通知调用者,可以在方法上声明异常。


public class TestThrows {
    
    //声明异常,多个异常可以用逗号隔开
    public void test()throws Exception,ClassNotFoundException{
        //可能会发生异常的代码
    }
}

处理方式一:调用者处理异常

public static void main(String[] args) {
    TestThrows t=new TestThrows();
    try {
        t.test();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

处理方式二:调用者继续声明异常

public static void main(String[] args) throws ClassNotFoundException, Exception {
    TestThrows t=new TestThrows();
    t.test();
}

main方法继续声明异常,调用者就变成虚拟机了,发生异常则按默认方式处理,打印出来。

抛出异常 throw

除了系统自动抛出的异常外,有些问题需要程序员自行抛出异常

public class TestThrow {
    public void inputAge(int age) throws Exception {
        if (age<1) {
            throw new Exception("还有这种年龄?");
        }
    }
    
    public static void main(String[] args) {
        TestThrow t=new TestThrow();
        try {
            t.inputAge(-1);
        } catch (Exception e) {
            System.out.println("年龄有误:"+e.getMessage());
        }
    }
}

自行抛出异常后,还需要在方法上声明异常

相关文章
|
1月前
|
安全 Java 数据库连接
2025 年最新 Java 学习路线图含实操指南助你高效入门 Java 编程掌握核心技能
2025年最新Java学习路线图,涵盖基础环境搭建、核心特性(如密封类、虚拟线程)、模块化开发、响应式编程、主流框架(Spring Boot 3、Spring Security 6)、数据库操作(JPA + Hibernate 6)及微服务实战,助你掌握企业级开发技能。
251 3
|
3月前
|
Java API 微服务
2025 年 Java 从入门到精通学习笔记全新版
《Java学习笔记:从入门到精通(2025更新版)》是一本全面覆盖Java开发核心技能的指南,适合零基础到高级开发者。内容包括Java基础(如开发环境配置、核心语法增强)、面向对象编程(密封类、接口增强)、进阶技术(虚拟线程、结构化并发、向量API)、实用类库与框架(HTTP客户端、Spring Boot)、微服务与云原生(容器化、Kubernetes)、响应式编程(Reactor、WebFlux)、函数式编程(Stream API)、测试技术(JUnit 5、Mockito)、数据持久化(JPA、R2DBC)以及实战项目(Todo应用)。
219 5
|
21天前
|
前端开发 Java 数据库连接
帮助新手快速上手的 JAVA 学习路线最详细版涵盖从入门到进阶的 JAVA 学习路线
本Java学习路线涵盖从基础语法、面向对象、异常处理到高级框架、微服务、JVM调优等内容,适合新手入门到进阶,助力掌握企业级开发技能,快速成为合格Java开发者。
266 3
|
1月前
|
NoSQL Java 关系型数据库
Java 从入门到进阶完整学习路线图规划与实战开发最佳实践指南
本文为Java开发者提供从入门到进阶的完整学习路线图,涵盖基础语法、面向对象、数据结构与算法、并发编程、JVM调优、主流框架(如Spring Boot)、数据库操作(MySQL、Redis)、微服务架构及云原生开发等内容,并结合实战案例与最佳实践,助力高效掌握Java核心技术。
218 1
|
1月前
|
Java 测试技术 API
Java IO流(二):文件操作与NIO入门
本文详解Java NIO与传统IO的区别与优势,涵盖Path、Files类、Channel、Buffer、Selector等核心概念,深入讲解文件操作、目录遍历、NIO实战及性能优化技巧,适合处理大文件与高并发场景,助力高效IO编程与面试准备。
|
1月前
|
Java 编译器 API
Java Lambda表达式与函数式编程入门
Lambda表达式是Java 8引入的重要特性,简化了函数式编程的实现方式。它通过简洁的语法替代传统的匿名内部类,使代码更清晰、易读。本文深入讲解Lambda表达式的基本语法、函数式接口、方法引用等核心概念,并结合集合操作、线程处理、事件回调等实战案例,帮助开发者掌握现代Java编程技巧。同时,还解析了面试中高频出现的相关问题,助你深入理解其原理与应用场景。
|
12天前
|
Java API 数据库
2025 年最新 Java 实操学习路线,从入门到高级应用详细指南
2025年Java最新实操学习路线,涵盖从环境搭建到微服务、容器化部署的全流程实战内容,助你掌握Java 21核心特性、Spring Boot 3.2开发、云原生与微服务架构,提升企业级项目开发能力,适合从入门到高级应用的学习需求。
235 0
|
22天前
|
监控 Java API
2025 年全新出炉的 Java 学习路线:从入门起步到实操精通的详细指南
2025年Java学习路线与实操指南,涵盖Java 21核心特性、虚拟线程、Spring Boot 3、微服务、Spring Security、容器化部署等前沿技术,助你从入门到企业级开发进阶。
187 0
|
1月前
|
前端开发 Java 数据库
Java 项目实战从入门到精通 :Java Web 在线商城项目开发指南
本文介绍了一个基于Java Web的在线商城项目,涵盖技术方案与应用实例。项目采用Spring、Spring MVC和MyBatis框架,结合MySQL数据库,实现商品展示、购物车、用户注册登录等核心功能。通过Spring Boot快速搭建项目结构,使用JPA进行数据持久化,并通过Thymeleaf模板展示页面。项目结构清晰,适合Java Web初学者学习与拓展。
181 1
|
1月前
|
算法 Java 测试技术
零基础学 Java: 从语法入门到企业级项目实战的详细学习路线解析
本文为零基础学习者提供完整的Java学习路线,涵盖语法基础、面向对象编程、数据结构与算法、多线程、JVM原理、Spring框架、Spring Boot及项目实战,助你从入门到进阶,系统掌握Java编程技能,提升实战开发能力。
110 0