《JAVA SE》认识异常

简介: 《JAVA SE》认识异常

前言

所谓异常指的就是程序在==运行时==出现错误时通知调用者的一种机制。


一、异常的基本语法

1.语法说明

        try{
            //有可能出现异常的语句 
        }[catch (异常类型 异常对象)] {
                //如何处理
        }[finally]{
            //异常的出口,最终会执行的代码块
        }
  1. try 代码块中放的是可能出现异常的代码.
  2. catch 代码块中放的是出现异常后的处理行为.
  3. finally 代码块中的代码用于处理善后工作, 会在最后执行.
  4. 其中 catch 和 finally 都可以根据情况选择加或者不加.

==若不处理异常:==

在这里插入图片描述我们发现一旦出现异常, 程序就终止了. after 没有正确输出。

==使用try..catch处理异常:==
在这里插入图片描述
我们发现, 一旦 try 中出现异常, 那么 try 代码块中的程序就不会继续执行, 而是交给 catch 中的代码来执行. catch 执行完毕会继续往下执行。

==注意事项:==

1. catch 只能处理对应种类的异常

java中一切皆是类,异常也是类,因此catch只能捕获相应的异常“类型”。
在这里插入图片描述

2. catch可以有多个

        int[] arr = {1, 2, 3};
        try {
            System.out.println("before");
            arr = null;
            System.out.println(arr[100]);
            System.out.println("after");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("这是个数组下标越界异常");
            e.printStackTrace();
        } catch (NullPointerException e) {
            System.out.println("这是个空指针异常");
            e.printStackTrace();
        }
        System.out.println("after try catch");

// 执行结果
before
这是个空指针异常
java.lang.NullPointerException
 at demo02.Test.main(Test.java:12)
after try catch

如果多个异常的处理方式是完全相同, 也可以写成这样:

catch (ArrayIndexOutOfBoundsException | NullPointerException e) {
 ...
}

3. 也可以用一个 catch 捕获所有异常(不推荐)

int[] arr = {1, 2, 3};
try {
    System.out.println("before");
    arr = null;
    System.out.println(arr[100]);
    System.out.println("after");
} catch (Exception e) {
    e.printStackTrace();
}
System.out.println("after try catch");

// 执行结果
before
java.lang.NullPointerException
 at demo02.Test.main(Test.java:12)
after try catch

由于 Exception 类是所有异常类的父类. 因此可以用这个类型表示捕捉所有异常.

备注: catch 进行类型匹配的时候, 不光会匹配相同类型的异常对象, 也会捕捉目标异常类型的子类对象.

4. finally 表示最后的善后工作, 例如释放资源

在这里插入图片描述在这里插入图片描述无论是否由异常产生,都会执行finally中的代码。

在这里插入图片描述
注意:
finally 执行的时机是在方法返回之前(try 或者 catch 中如果有 return 会在这个 return 之前执行 finally). 但是如果finally 中也存在 return 语句, 那么就会执行 finally 中的 return, 从而不会执行到 try 中原有的 return.

一般我们不建议在 finally 中写 return (被编译器当做一个警告).

2.打印错误堆栈信息

关于 "调用栈"
方法之间是存在相互调用关系的, 这种调用关系我们可以用 "调用栈" 来描述。 在 JVM 中有一块内存空间称为 "虚拟机栈" 专门存储方法之间的调用关系。当代码中出现异常的时候, 我们就可以使用 e.printStackTrace(); 的方式查看出现异常代码的调用栈。

在这里插入图片描述

3.异常处理流程

  1. 程序先执行 try 中的代码
  2. 如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.
  3. 如果找到匹配的异常类型, 就会执行 catch 中的代码
  4. 如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.

无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).

  1. 如果上层调用者也没有处理的了异常, 就继续向上传递.
  2. 一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止

在这里插入图片描述

4.throw和throws关键字

==throw:用在方法内部,表示人为产生异常并抛出==

在这里插入图片描述
异常对象的产生都是发生异常后JVM产生的,若需要人为产生异常对象,就使用throw关键字。

==throws:用在方法声明上,表示该方法可能会产生的异常类型,但本方法中不处理该异常,若出现异常则抛回给调用者。==

在这里插入图片描述

二、Java异常体系

Java中的异常分为两大类:一类叫做受查异常,另一类叫做非受查异常

下图为Java内置的异常类之间的继承关系:

在这里插入图片描述

  1. 顶层类 Throwable 派生出两个重要的子类, ErrorException
  2. 其中 Error 指的是 Java 运行时内部错误和资源耗尽错误. 应用程序不抛出此类异常. 这种内部错误一旦出现,除了告知用户并使程序终止之外, 再无能无力. 这种情况很少出现.
  3. Exception 是我们程序猿所使用的异常类的父类.
  4. 其中 Exception 有一个子类称为 RuntimeException , 这里面又派生出很多我们常见的异常。

在这里插入图片描述在这里插入图片描述在这里插入图片描述

==如果一段代码可能抛出 受查异常, 那么必须显式进行处理:==

    public static void main(String[] args) {
        System.out.println(readFile());
    }


    public static String readFile() {
        // 尝试打开文件, 并读其中的一行. 
        File file = new File("d:/test.txt");
        // 使用文件对象构造 Scanner 对象. 
        Scanner sc = new Scanner(file);
        return sc.nextLine();
    }
    
// 编译出错
    Error:(13, 22) java: 未报告的异常错误java.io.FileNotFoundException; 必须对其进行捕获或声明以便抛出

查看 Scanner 的构造方法可以发现, 存在 FileNotFoundException 这样的异常说明:

在这里插入图片描述

FileNotFoundException 这样的异常就是受查异常. 如果不显式处理, 编译无法通过。

==显示处理:==

  1. 进行try...catch捕获这个异常。

在这里插入图片描述

  1. 调用者也使用throws向上抛出异常。

在这里插入图片描述

三、自定义异常类

Java 中虽然已经内置了丰富的异常类, 但是我们实际场景中可能还有一些情况需要我们对异常类进行扩展, 创建符合我们实际情况的异常.

例如, 我们实现一个用户登陆功能:

public class Test { 
 private static String userName = "admin"; 
 private static String password = "123456"; 

 public static void main(String[] args) { 
 login("admin", "123456"); 
 } 


 public static void login(String userName, String password) { 
 if (!Test.userName.equals(userName)) { 
 // TODO 处理用户名错误
 } 
 if (!Test.password.equals(password)) { 
 // TODO 处理密码错误
 } 
 System.out.println("登陆成功"); 
 } 
}

此时我们在处理用户名密码错误的时候可能就需要抛出两种异常. 我们可以基于已有的异常类进行扩展(继承), 创建和我们业务相关的异常类.

class UserError extends Exception { 
 public UserError(String message) { 
 super(message); 
 } 
} 
class PasswordError extends Exception { 
 public PasswordError(String message) { 
 super(message); 
 } 
}

此时我们的 login 代码可以改成:

public static void main(String[] args) { 
 try { 
 login("admin", "123456"); 
 } catch (UserError userError) { 
 userError.printStackTrace(); 
 } catch (PasswordError passwordError) { 
 passwordError.printStackTrace(); 
 } 
} 
public static void login(String userName, String password) throws UserError, 
PasswordError { 
 if (!Test.userName.equals(userName)) { 
 throw new UserError("用户名错误"); 
 } 
 if (!Test.password.equals(password)) { 
 throw new PasswordError("密码错误"); 
 } 
 System.out.println("登陆成功"); 
} 

==注意事项:==

  • 自定义异常通常会继承自 Exception 或者 RuntimeException
  • 继承自 Exception 的异常默认是受查异常
  • 继承自 RuntimeException 的异常默认是非受查异常

总结

由于博主之前忙着赶开题报告以及各类竞赛,好久没有更新了😃😃😃,有帮助的话恳请各位老铁三连+关注~~~博主将持续更新后续进阶内容!!!

相关文章
|
Java
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
360 1
|
2月前
|
安全 Java API
Java SE 与 Java EE 区别解析及应用场景对比
在Java编程世界中,Java SE(Java Standard Edition)和Java EE(Java Enterprise Edition)是两个重要的平台版本,它们各自有着独特的定位和应用场景。理解它们之间的差异,对于开发者选择合适的技术栈进行项目开发至关重要。
350 1
|
5月前
|
Java 程序员 数据库连接
我们详细地讲解一下 Java 异常及要如何处理
我是小假 期待与你的下一次相遇 ~
129 1
|
Java API 调度
如何避免 Java 中的 TimeoutException 异常
在Java中,`TimeoutException`通常发生在执行操作超过预设时间时。要避免此异常,可以优化代码逻辑,减少不必要的等待;合理设置超时时间,确保其足够完成正常操作;使用异步处理或线程池管理任务,提高程序响应性。
548 13
|
Java
在 Java 中,如何自定义`NumberFormatException`异常
在Java中,自定义`NumberFormatException`异常可以通过继承`IllegalArgumentException`类并重写其构造方法来实现。自定义异常类可以添加额外的错误信息或行为,以便更精确地处理特定的数字格式转换错误。
208 1
|
5月前
|
设计模式 算法 Java
Java SE 与 Java EE 组件封装使用方法及实践指南
本指南详细介绍了Java SE与Java EE的核心技术使用方法及组件封装策略。涵盖集合框架、文件操作、Servlet、JPA、EJB和RESTful API的使用示例,提供通用工具类与基础组件封装建议,如集合工具类、文件工具类、基础Servlet、实体基类和服务基类等。同时,通过分层架构集成示例展示Servlet、EJB和JPA的协同工作,并总结组件封装的最佳实践,包括单一职责原则、接口抽象、依赖注入、事务管理和异常处理等。适合希望提升代码可维护性和扩展性的开发者参考。
187 0
|
8月前
|
SQL Java 中间件
【YashanDB知识库】yasdb jdbc驱动集成BeetISQL中间件,业务(java)报autoAssignKey failure异常
在BeetISQL 2.13.8版本中,客户使用batch insert向yashandb表插入数据并尝试获取自动生成的sequence id时,出现类型转换异常。原因是beetlsql在prepareStatement时未指定返回列,导致yashan JDBC驱动返回rowid(字符串),与Java Bean中的数字类型tid不匹配。此问题影响业务流程,使无法正确获取sequence id。解决方法包括:1) 在batchInsert时不返回自动生成的sequence id;2) 升级至BeetISQL 3,其已修正该问题。
【YashanDB知识库】yasdb jdbc驱动集成BeetISQL中间件,业务(java)报autoAssignKey failure异常
|
8月前
|
SQL druid Oracle
【YashanDB知识库】yasdb jdbc驱动集成druid连接池,业务(java)日志中有token IDENTIFIER start异常
客户Java日志中出现异常,影响Druid的merge SQL功能(将SQL字面量替换为绑定变量以统计性能),但不影响正常业务流程。原因是Druid在merge SQL时传入null作为dbType,导致无法解析递归查询中的`start`关键字。
|
9月前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
591 14
|
9月前
|
缓存 Java 应用服务中间件
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
1731 5