编辑推荐: |
本文主要介绍Java异常处理相关知识。希望能对遇到类似问题的同学有所帮助。
本文来自于CSDN,由火龙果软件Linda编辑、推荐。 |
|
一、程序错误
在Java程序中,错误通常分为三类:编译时错误、运行时错误和逻辑错误。
1.编译时错误:编译时错误是指在编译Java程序时发生的错误。这些错误通常是由于语法错误或类型不匹配等问题导致的。例如,下面的代码将无法通过编译,因为它试图将一个字符串赋值给一个整型变量:
2.运行时错误:运行时错误是指在程序运行过程中发生的错误。这些错误通常是由于程序中的异常情况导致的,例如除以零、空指针引用等。运行时错误会导致程序崩溃并抛出异常。例如,下面的代码将在运行时抛出ArithmeticException异常,因为它试图除以零:
= 10 / 0; // 运行 时错误,抛出ArithmeticException异常
|
3.逻辑错误:逻辑错误是指程序虽然能够正常编译和运行,但是其行为与预期不符。这些错误通常是由于程序员在编写代码时犯了逻辑错误导致的。例如,下面的代码本意是计算两个数的平均值,但由于程序员犯了一个简单的逻辑错误,导致结果不正确:
erage = x + y / 2; // 逻辑错误,应该写成 (x + y) / 2
|
二、异常
2.1概述
异常是程序执行期间发生的意外事件。它影响程序指令流,从而导致程序异常终止。
2.2产生原因
无效的用户输入
设备故障
网络连接丢失
物理限制(磁盘内存不足)
代码错误
打开一个不可用的文件
2.3Java 异常层次结构 从上图可以看到,Throwable类是层次结构中的根类。
请注意,层次结构分为两个分支:错误(Error)和异常(Exception)。
Error
Error表示不可恢复的情况,例如Java虚拟机(JVM)内存不足,内存泄漏,堆栈溢出错误,库不兼容,无限递归等。
错误通常是程序员无法控制的,我们不应该尝试处理错误。
出现严重的,无法恢复运行状态的错误,出现错误后一般只能进行详细的日志记录汇报
Exception
程序可以捕获并处理异常。
当方法内发生异常时,它将创建一个对象。该对象称为异常对象。
它包含有关异常的信息,例如异常的名称和说明以及发生异常时的程序状态。例如空指针访问 试图读取不存在的文件
网络连接中断
分类:受检(编译时)异常和非受检(运行时)异常
2.3.1非受检异常
非受检异常(运行时异常) 是指编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该积极避免其出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常。
对于这类异常,可以不作处理或者加上逻辑判断。
运行中不应该出现而又出现的问题,此类异常一般是由于代码(逻辑)错误(不严谨)产生的,不应通过捕获异常处理,而应通过修正代码更正错误解决
2.3.2受检异常
是指要求必须处置的异常。即程序在运行时由于外界因素造成的一般性异常。编译器要求java程序必须捕获或声明所有编译时异常。
对于这类异常,如果程序不处理,可能会带来意想不到的结果。
一般为程序与程序控制之外的外部资源互交时,产生的错误 如文件无法读取,数据库无法访问,网络无法连接等
程序必须为可能出现的受检异常,提供异常处理程序,从而使程序可以继续运行而非停止崩溃
2.3.3常用异常:
三、异常处理机制
3.1概述
异常处理机制是编程语言或计算机硬件里的一种机制,用于处理软件或信息系统中出现的异常状况,即超出程序正常执行流程的某些特殊条件。它让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰。
调用栈Call Stack
调用栈(Call Stack)是计算机内部一种用来跟踪程序运行状态的数据结构,类似于人们在日常生活中的“记事本”,记录了程序在运行过程中每一个函数调用的位置、参数和返回值等信息。它是计算机科学中存储有关正在运行的子程序的消息的栈
3.2异常类型的实现
Java提供了3种主要的异常类型的实现
java.lang.Error,继承自Throwable,
非受检 java.lang.Exception,继承自Throwable,受检异常
java.lang.RuntimeException ,继承自Exception,运行时异常,非受检异常 java.lang.Throwable类,所有错误/异常的超类,仅Throwable及其子类对象可以被catch语句捕获
3.3异常处理的关键字:异常处理的关键字:
捕获异常:
try:执行可能产生异常的代码;
catch:捕获异常;
finally:无论是否发生异常,代码总被执行;
抛出异常:
throw:异常生成阶段,手动抛出异常对象;
声明异常:
throws声明方法可能要抛出的各种异常类
3.3.1try-catch Block
public static void main(String[] args) { int[] numbers = {1, 2, 3}; System.out.println(numbers[3]); System.out.println(3 / 0); } catch (ArrayIndexOut OfBoundsException e) { System.out.println ("数组越界!"); } catch (ArithmeticException e) { System.out. println("算术异常!");
|
将多个可能引发异常的代码 置于一个try块中 顺次声明多个catch与之关联
在try代码块与catch代码块之间,禁止定义其他代码 补充块变量的作用范围
块变量(也称为局部变量)是在代码块(如方法、循环或条件语句)中定义的变量。它们的作用范围仅限于定义它们的代码块。当代码块执行完毕后,块变量将不再可用。
public static void main(String[] args) { System.out. println("x: " + x + ", y: " + y); System.out. println("x: " + x);
|
补充Try-catch的执行顺序3.3.2Throwable 类常用方法
Throwable 类是 Java 语言中所有错误或异常的超类。它包含了一些常用的方法,可以帮助我们获取有关异常的信息,以下是一些常用的方法:
getMessage():返回此 throwable 的详细消息字符串。
printStackTrace():将此 throwable 及其追踪输出至标准错误流。这个方法会打印出异常的类型、详细消息以及异常发生时的堆栈信息。
toString():返回此 throwable 的简短描述。这个方法返回的字符串包含了异常的类型和详细消息。
getCause():返回此 throwable 的原因。如果原因不存在或未知,则返回 null。
public static void main(String[] args) { System.out. println(3 / 0); } catch (ArithmeticException e) { System.out.println("异常 类型: " + e); System.out.println("异 常信息: " + e.getMessage()); System.out.println("堆栈信息: "); System.out.println("原 因: " + e.getCause());
|
3.3.3finally 块
finally 块是与 try-catch 语句一起使用的一个可选代码块。它包含的代码无论是否发生异常都会被执行。通常,我们在
finally 块中放置一些清理资源的代码,例如关闭文件、释放内存等。
public static void main(String[] args) { System.out. println(3 / 0); } catch (Arithmetic Exception e) { System.out. println("算术异常!"); System.out. println("清理资源...");
|
Try-catch-finally,执行顺序
包含return语句时,try-catch-finally的执行顺序
总结
Finally块仅用于释放资源,禁止参与业务逻辑的处理,块内禁止使用return语句
3.3.4try-with-resources语句
try-with-resources语句是Java 7中引入的一种try语句,旨在减轻开发人员释放try块中使用的资源的义务。它的全部想法是,开发人员无需担心仅在一个try-catch-finally块中使用的资源的资源管理。这是通过消除对finally块的需要而实现的,实际上,开发人员仅在关闭资源时才使用块。此外,使用try-with-resources的代码通常更清晰易读,因此使代码更易于管理,尤其是当我们处理许多try块时
static String readFirstLine FromFile(String path) throws IOException { try (FileReader fr = new FileReader(path); BufferedReader br = new BufferedReader(fr)) {
|
在这个例子中,声明在try-with-resources语句中的资源是一个FileReader和一个BufferedReader。这些资源的声明语句出现在紧跟在try关键字后面的括号内。在Java
SE 7及更高版本中,类FileReader和BufferedReader实现了接口java.lang.AutoCloseable。由于在一个带有资源的try语句中声明了FileReader和BufferedReader实例,因此无论try语句是正常完成还是突然完成(由于方法BufferedReader.readLine抛出IOException),它们都将被关闭。
3.3.5 throw和throws 关键字
当方法没有捕获到可能发生的受检异常时,方法必须指定抛出受检异常 通过在方法声明添加throws子句,实现在方法抛出异常;在方法参数列表后(),方法体前{};方法抛出的所有异常使用“,”逗号分隔;
throw和throws是两个不同的关键字,它们都与异常处理有关。
throws关键字用于方法声明,用来指定该方法可能抛出的异常类型。它表示出现异常的一种可能性,但并不一定会发生这些异常。例如:
public void myMethod() throws IOException {
|
而throw关键字用于方法体内,用来显式地抛出一个异常对象。执行throw则一定抛出了某种异常对象。例如:
throw new IOException("发生了IO异常");
|
Java throws 和throw关键字
import java.io.IOException; public class ThrowsExample { public static void main(String[] args) { } catch (IOException e) { System.out.println ("捕获到了异常: " + e.getMessage()); public static void myMethod() throws IOException { throw new IOException("发生了IO异常");
|
简单来说,throws关键字用于声明一个方法可能抛出的所有异常信息,而throw则是指抛出的一个具体的异常类型。
注意
3.3.6自定义异常
在Java中,除了可以使用系统提供的异常类之外,还可以自定义异常类。自定义异常类通常用来表示程序中特定的异常情况。
public class CustomExceptionExample { public static void main(String[] args) { if (score < 0 || score > 100) { throw new Invalid ScoreException("分数 值无效: " + score); System.out. println("分数值有效: " + score); } catch (Invalid ScoreException e) { System.out. println(e.getMessage()); class InvalidScoreException extends Exception { public InvalidScoreException (String message) {
|
|