异常的类型
检查性异常
用户错误或问题引起的异常,这些异常在编译时强制要求程序员处理。通常使用try-catch块来捕获异常,或在方法声明中使用throws子句声明方法可能抛出的异常。
try{
//可能抛出异常的代码
} catch(IOException e){
//处理异常的代码
}
//或者
public void readFile() throws IOException{
//可能出现异常的代码
}
运行时异常
编译时不要求强制处理,通常是由程序中的错误引起的。这类异常可以选择处理,并非强制要求。
try{
//可能异常的代码
} catch (NullPointerException e){
//处理异常的代码
}
错误
错误不是异常,而是脱离程序员控制的问题,通常在代码中被忽略。
java中支持异常处理的关键字
- try:用于包裹可能会抛出异常的代码块
- catch:用于捕获并处理异常的代码块
- finally:用于包含无论是否发生异常都要执行的代码块
- throw:用于手动抛出异常
- throws:用于在方法中指明方法可能抛出异常
- Exception类:所有异常的父类
Exception类的层次
所有的异常类是从java.lang.Exception类继承的子类
Exception类是Throwable类的子类,除了Exception类外,Throwable还有一个子类error
Error用来指示运行时环境发生的错误
Throwable类的主要方法
捕获异常
// 文件名 : ExcepTest.java
import java.io.*;
public class ExcepTest{
public static void main(String args[]){
try{
int a[] = new int[2];
System.out.println("Access element three :" + a[3]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("Exception thrown :" + e);
}
System.out.println("Out of the block");
}
}
多重捕获块
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型3 异常的变量名3){
// 程序代码
}
如果保护代码中发生异常,异常被抛给第一个 catch 块。
如果抛出异常的数据类型与 ExceptionType1 匹配,它在这里就会被捕获。
如果不匹配,它会被传递给第二个 catch 块。
如此,直到异常被捕获或者通过所有的 catch 块。
throw关键字
用于在当前方法中抛出一个异常
public void checkNumber(int num) {
if (num < 0) {
throw new IllegalArgumentException("Number must be positive");
}
}
throws关键字
用于在方法声明中指定该方法可能抛出的异常。当方法内部抛出指定类型的异常时,该异常会被传递给调用该方法的代码,并在该代码中处理异常。
例如,下面的代码中,当 readFile 方法内部发生 IOException 异常时,会将该异常传递给调用该方法的代码。在调用该方法的代码中,必须捕获或声明处理 IOException 异常。
public void readFile(String filePath) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(filePath));
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
}
reader.close();
}
一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。
import java.io.*;
public class className
{
public void withdraw(double amount) throws RemoteException,
InsufficientFundsException
{
// Method implementation
}
//Remainder of class definition
}
finally关键字
用来创建在try代码块后面执行的代码块,无论是否发生异常,finally代码块总会被执行
可以运行清理类型的收尾善后类语句
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
try-with-resources
旨在自动管理资源,确保资源在使用后能够及时关闭,避免资源泄露 。
try-with-resources 是一种异常处理机制,它能够自动关闭在 try 块中声明的资源,无需显式地在 finally 块中关闭。
在 try-with-resources 语句中,你只需要在 try 关键字后面声明资源,然后跟随一个代码块。无论代码块中的操作是否成功,资源都会在 try 代码块执行完毕后自动关闭。
try (resource declaration) {
// 使用的资源
} catch (ExceptionType e1) {
// 异常块
}
import java.io.*;
public class RunoobTest {
public static void main(String[] args) {
String line;
try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
while ((line = br.readLine()) != null) {
System.out.println("Line =>"+line);
}
} catch (IOException e) {
System.out.println("IOException in try block =>" + e.getMessage());
}
}
}
try-with-resources可以处理多个资源,用分号分隔
import java.io.*;
import java.util.*;
class RunoobTest {
public static void main(String[] args) throws IOException{
try (Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
while (scanner.hasNext()) {
writer.print(scanner.nextLine());
}
}
}
}
声明自定义异常
- 所有的异常都必须是Throwable的子类
- 检查性异常类需要继承Exception类
- 运行时异常类需要继承RuntimeException类
class MyException extends Exception{
}
示例:
InsufficientFundsException.java:
// 文件名InsufficientFundsException.java
import java.io.*;
//自定义异常类,继承Exception类
public class InsufficientFundsException extends Exception
{
//此处的amount用来储存当出现异常(取出钱多于余额时)所缺乏的钱
private double amount;
public InsufficientFundsException(double amount)
{
this.amount = amount;
}
public double getAmount()
{
return amount;
}
}
CheckingAccount.java:
// 文件名称 CheckingAccount.java
import java.io.*;
//此类模拟银行账户
public class CheckingAccount
{
//balance为余额,number为卡号
private double balance;
private int number;
public CheckingAccount(int number)
{
this.number = number;
}
//方法:存钱
public void deposit(double amount)
{
balance += amount;
}
//方法:取钱
public void withdraw(double amount) throws
InsufficientFundsException
{
if(amount <= balance)
{
balance -= amount;
}
else
{
double needs = amount - balance;
throw new InsufficientFundsException(needs);
}
}
//方法:返回余额
public double getBalance()
{
return balance;
}
//方法:返回卡号
public int getNumber()
{
return number;
}
}
BankDemo.java:
//文件名称 BankDemo.java
public class BankDemo
{
public static void main(String [] args)
{
CheckingAccount c = new CheckingAccount(101);
System.out.println("Depositing $500...");
c.deposit(500.00);
try
{
System.out.println("\nWithdrawing $100...");
c.withdraw(100.00);
System.out.println("\nWithdrawing $600...");
c.withdraw(600.00);
}catch(InsufficientFundsException e)
{
System.out.println("Sorry, but you are short $"
+ e.getAmount());
e.printStackTrace();
}
}
}