目录
一、程序错误
二、异常
2.1概述
2.2产生原因
2.3Java 异常层次结构
Error
Exception
2.3.1非受检异常
2.3.2受检异常
三、异常处理机制
3.1概述
编辑
调用栈Call Stack
3.2异常类型的实现
3.3异常处理的关键字:
3.3.1try-catch Block
编辑
补充块变量的作用范围
补充Try-catch的执行顺序
3.3.2Throwable 类常用方法
3.3.3finally 块
3.3.4try-with-resources语句
3.3.5 throw和throws 关键字
3.3.6自定义异常
一、程序错误
在Java程序中,错误通常分为三类:编译时错误、运行时错误和逻辑错误。
1.编译时错误:编译时错误是指在编译Java程序时发生的错误。这些错误通常是由于语法错误或类型不匹配等问题导致的。例如,下面的代码将无法通过编译,因为它试图将一个字符串赋值给一个整型变量:
int x = "hello"; // 编译时错误
2.运行时错误:运行时错误是指在程序运行过程中发生的错误。这些错误通常是由于程序中的异常情况导致的,例如除以零、空指针引用等。运行时错误会导致程序崩溃并抛出异常。例如,下面的代码将在运行时抛出ArithmeticException异常,因为它试图除以零:
int x = 10 / 0; // 运行时错误,抛出ArithmeticException异常
3.逻辑错误:逻辑错误是指程序虽然能够正常编译和运行,但是其行为与预期不符。这些错误通常是由于程序员在编写代码时犯了逻辑错误导致的。例如,下面的代码本意是计算两个数的平均值,但由于程序员犯了一个简单的逻辑错误,导致结果不正确:
int x = 10;
int y = 20;
int average = 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 class Example {
public static void main(String[] args) {
int[] numbers = {1, 2, 3};
try {
// 尝试访问数组中不存在的元素
System.out.println(numbers[3]);
// 尝试将整数除以零
System.out.println(3 / 0);
} catch (ArrayIndexOutOfBoundsException e) {
// 捕获并处理数组越界异常
System.out.println("数组越界!");
} catch (ArithmeticException e) {
// 捕获并处理算术异常
System.out.println("算术异常!");
}
}
}
将多个可能引发异常的代码 置于一个try块中 顺次声明多个catch与之关联
在try代码块与catch代码块之间,禁止定义其他代码
补充块变量的作用范围
块变量(也称为局部变量)是在代码块(如方法、循环或条件语句)中定义的变量。它们的作用范围仅限于定义它们的代码块。当代码块执行完毕后,块变量将不再可用。
public class Example {
public static void main(String[] args) {
// 定义一个块变量
int x = 10;
if (x > 5) {
// 定义另一个块变量
int y = 20;
System.out.println("x: " + x + ", y: " + y);
}
// 这里无法访问块变量 y,因为它已经超出了作用范围
System.out.println("x: " + x);
}
}
补充Try-catch的执行顺序
3.3.2Throwable
类常用方法
Throwable
类是 Java 语言中所有错误或异常的超类。它包含了一些常用的方法,可以帮助我们获取有关异常的信息,以下是一些常用的方法:
getMessage()
:返回此 throwable 的详细消息字符串。printStackTrace()
:将此 throwable 及其追踪输出至标准错误流。这个方法会打印出异常的类型、详细消息以及异常发生时的堆栈信息。toString()
:返回此 throwable 的简短描述。这个方法返回的字符串包含了异常的类型和详细消息。getCause()
:返回此 throwable 的原因。如果原因不存在或未知,则返回 null。
public class Example {
public static void main(String[] args) {
try {
// 尝试将整数除以零
System.out.println(3 / 0);
} catch (ArithmeticException e) {
// 获取并打印异常信息
System.out.println("异常类型: " + e);
System.out.println("异常信息: " + e.getMessage());
System.out.println("堆栈信息: ");
e.printStackTrace();
System.out.println("原因: " + e.getCause());
}
}
}
3.3.3finally
块
finally
块是与try-catch
语句一起使用的一个可选代码块。它包含的代码无论是否发生异常都会被执行。通常,我们在finally
块中放置一些清理资源的代码,例如关闭文件、释放内存等。
public class Example {
public static void main(String[] args) {
try {
// 尝试将整数除以零
System.out.println(3 / 0);
} catch (ArithmeticException e) {
// 捕获并处理算术异常
System.out.println("算术异常!");
} finally {
// 无论是否发生异常,都会执行这里的代码
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 readFirstLineFromFile(String path) throws IOException {
// try-with-resources语句,声明了两个资源:FileReader和BufferedReader
try (FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr)) {
// 从文件中读取第一行
return br.readLine();
}
// 在try块结束后,资源会被自动关闭
}
在这个例子中,声明在
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
则一定抛出了某种异常对象。例如:public void myMethod() { // ... throw new IOException("发生了IO异常"); }
Java throws 和throw关键字
import java.io.IOException;
public class ThrowsExample {
public static void main(String[] args) {
try {
myMethod();
} catch (IOException e) {
// 处理异常
System.out.println("捕获到了异常: " + e.getMessage());
}
}
public static void myMethod() throws IOException {
// 方法体
// 如果在方法体中发生了IO异常,可以抛出
throw new IOException("发生了IO异常");
}
}
简单来说,
throws
关键字用于声明一个方法可能抛出的所有异常信息,而throw
则是指抛出的一个具体的异常类型。
注意
3.3.6自定义异常
在Java中,除了可以使用系统提供的异常类之外,还可以自定义异常类。自定义异常类通常用来表示程序中特定的异常情况。
public class CustomExceptionExample {
public static void main(String[] args) {
int score = -5;
try {
if (score < 0 || score > 100) {
throw new InvalidScoreException("分数值无效: " + score);
}
System.out.println("分数值有效: " + score);
} catch (InvalidScoreException e) {
// 处理异常
System.out.println(e.getMessage());
}
}
}
class InvalidScoreException extends Exception {
public InvalidScoreException(String message) {
super(message);
}
}