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
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
66 1
|
1月前
|
Java API 调度
如何避免 Java 中的 TimeoutException 异常
在Java中,`TimeoutException`通常发生在执行操作超过预设时间时。要避免此异常,可以优化代码逻辑,减少不必要的等待;合理设置超时时间,确保其足够完成正常操作;使用异步处理或线程池管理任务,提高程序响应性。
73 12
|
1月前
|
Java
在 Java 中,如何自定义`NumberFormatException`异常
在Java中,自定义`NumberFormatException`异常可以通过继承`IllegalArgumentException`类并重写其构造方法来实现。自定义异常类可以添加额外的错误信息或行为,以便更精确地处理特定的数字格式转换错误。
39 1
|
25天前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
46 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
21天前
|
监控 架构师 Java
Java虚拟机调优的艺术:从入门到精通####
本文作为一篇深入浅出的技术指南,旨在为Java开发者揭示JVM调优的神秘面纱,通过剖析其背后的原理、分享实战经验与最佳实践,引领读者踏上从调优新手到高手的进阶之路。不同于传统的摘要概述,本文将以一场虚拟的对话形式,模拟一位经验丰富的架构师向初学者传授JVM调优的心法,激发学习兴趣,同时概括性地介绍文章将探讨的核心议题——性能监控、垃圾回收优化、内存管理及常见问题解决策略。 ####
|
1月前
|
IDE 前端开发 Java
怎样避免 Java 中的 NoSuchFieldError 异常
在Java中避免NoSuchFieldError异常的关键在于确保类路径下没有不同版本的类文件冲突,避免反射时使用不存在的字段,以及确保所有依赖库版本兼容。编译和运行时使用的类版本应保持一致。
73 7
|
1月前
|
Java 编译器
如何避免在 Java 中出现 NoSuchElementException 异常
在Java中,`NoSuchElementException`通常发生在使用迭代器、枚举或流等遍历集合时,尝试访问不存在的元素。为了避免该异常,可以在访问前检查是否有下一个元素(如使用`hasNext()`方法),或者使用`Optional`类处理可能为空的情况。正确管理集合边界和条件判断是关键。
80 6
|
1月前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
1月前
|
Java
Java异常捕捉处理和错误处理
Java异常捕捉处理和错误处理
68 1
|
1月前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。