无涯教程-Java - 异常处理

45 阅读6分钟

异常是在程序执行过程中出现的问题,当发生异常时,程序的正常流程被中断。

如果在程序中使用FileReader类从文件中读取数据,如果在其构造函数中指定的文件不存在,则会发生FileNotFoundException,编译器会提示程序员处理异常。

import java.io.File;
import java.io.FileReader;

public class FilenotFound_Demo {

public static void main(String args[]) { File file = new File("E://file.txt"); FileReader fr = new FileReader(file); } }

如果您尝试编译上述程序,您将得到以下异常。

C:\>javac FilenotFound_Demo.java
FilenotFound_Demo.java:8: error: unreported exception FileNotFoundException; must be caught or declared to be thrown
      FileReader fr=new FileReader(file);
                      ^
1 error

注意-由于FileReader类的read()和close()方法抛出IOException,编译器通知处理IOException以及FileNotFoundException

public class Unchecked_Demo {

public static void main(String args[]) { int num[] = {1, 2, 3, 4}; System.out.println(num[5]); } }

如果您编译并执行上述程序,您将得到以下异常。

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
	at Exceptions.Unchecked_Demo.main(Unchecked_Demo.java:8)

层次结构

所有异常类都是java.lang.Exception类的子类型。Exception类是Throwable类的子类。除了Exception类之外,还有一个名为Error的子类,它是从Throwable类派生的。

Exception类有两个主要的子类:IOException类和RuntimeException类。

Exceptions1

异常方法

下面是Throwable类中可用的重要方法的列表。

Sr.No. Method & Remark
1

public String getMessage()

返回有关已发生异常的详细消息。

2

public Throwable getCause()

返回Throwable对象表示的异常原因。

3

public String toString()

返回与getMessage()输出连接的类名。

4

public void printStackTrace()

将toString()的输出与堆栈跟踪一起打印到System.err,即错误输出流。

5

public StackTraceElement[]getStackTrace()

返回一个数组,其中包含堆栈跟踪中的每个元素。

6

public  Throwable fillInStackTrace()

使用当前堆栈跟踪填充此Throwable对象的堆栈跟踪,并添加到堆栈跟踪中的任何以前的信息。

捕获异常

方法使用try和catch关键字的组合捕获异常。try/catch块中的代码称为受保护代码,语法如下-

try {
   //Protected code
} catch (ExceptionName e1) {
   //Catch block
}

容易发生异常的代码放在try块中m当发生异常时,发生的异常由与其关联的catch块处理。每个try块后面都应该紧跟着catch块或final块。

Try...catch 示例

下面是一个用2个元素声明的数组。然后代码尝试访问引发异常的数组的3rd元素。

//File Name : 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"); } }

这将产生以下输出-

Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
Out of the block

多个捕获异常

TRY块之后可以跟随多个CATCH块。多个CATCH块的语法类似于以下-

try {
   //Protected code
} catch (ExceptionType1 e1) {
   //Catch block
} catch (ExceptionType2 e2) {
   //Catch block
} catch (ExceptionType3 e3) {
   //Catch block
}

下面是显示如何使用多个try/catch语句的代码段。

try {
   file = new FileInputStream(fileName);
   x = (byte) file.read();
} catch (IOException i) {
   i.printStackTrace();
   return -1;
} catch (FileNotFoundException f) //Not valid! {
   f.printStackTrace();
   return -1;
}

捕获多种异常

从Java7开始,您可以使用单个catch块处理多个异常,该特性简化了代码。下面是你会怎么做-

catch (IOException|FileNotFoundException ex) {
   logger.log(ex);
   throw ex;

Throws/Throw 关键字

如果不想处理异常,则可以使用throws关键字往外抛出异常。

下面的方法声明它抛出一个RemoteException-

import java.io.*;
public class className {

public void deposit(double amount) throws RemoteException { //方法实现 throw new RemoteException(); } //Remainder of class definition }

一个方法可以声明它抛出了多个异常,在这种情况下,异常是在一个用逗号分隔的列表中声明的。如下面的方法声明它抛出了一个RemoteException和一个InassessentFundsException-

import java.io.*;
public class className {

public void withdraw(double amount) throws RemoteException, InsufficientFundsException { //Method implementation } //Remainder of class definition }

Finally块

Finally块位于try块或catch块之后。始终执行final代码块,而不管有没有异常。

使用Finally块允许您运行要执行的任何清理类型语句,无论代码中发生了什么。

try {
   //Protected code
} catch (ExceptionType1 e1) {
   //Catch block
} catch (ExceptionType2 e2) {
   //Catch block
} catch (ExceptionType3 e3) {
   //Catch block
}finally {
   //The finally block always executes.
}

Finally 示例

public class ExcepTest {

public static void main(String args[]) { int a[] = new int[2]; try { System.out.println("Access element three :" + a[3]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Exception thrown :" + e); }finally { a[0] = 6; System.out.println("First element value: " + a[0]); System.out.println("The finally statement is executed"); } } }

这将产生以下输出-

Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
First element value: 6
The finally statement is executed

try-with-resources

通常,当无涯教程使用任何资源(如流,连接等)时,必须使用finally块显式关闭它们。 在下面的程序中,使用FileReader从文件中读取数据,并使用finally块将其关闭。

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ReadData_Demo {

public static void main(String args[]) { FileReader fr = null; try { File file = new File("file.txt"); fr = new FileReader(file); char [] a = new char[50]; fr.read(a); //将内容读取到数组 for(char c : a) System.out.print(c); //一个一个地打印字符 } catch (IOException e) { e.printStackTrace(); }finally { try { fr.close(); } catch (IOException ex) { ex.printStackTrace(); } } } }

try-with-resources,也称为自动资源管理,是Java 7中引入的一种新的异常处理机制,它会自动关闭try catch块中使用的资源。

要使用此语句,只需在括号内声明所需的资源,创建的资源将在块结束时自动关闭。以下是try-with-resources语句的语法。

try(FileReader fr=new FileReader("file path")) {
   //use the resource
   } catch () {
      //body of catch 
   }
}

下面是使用try-with-resources语句读取文件中的数据的程序。

import java.io.FileReader;
import java.io.IOException;

public class Try_withDemo {

public static void main(String args[]) { try(FileReader fr = new FileReader("E://file.txt")) { char [] a = new char[50]; fr.read(a); //将内容读取到数组 for(char c : a) System.out.print(c); //一个一个地打印字符 } catch (IOException e) { e.printStackTrace(); } } }

自定义异常

无涯教程可以定义自己的异常类,如下所示-

class MyException extends Exception {
}

您只需要扩展预定义的Exception类来创建您自己的异常,这些被认为是检查异常。以下InassessentFundsException类是用户定义的异常,它扩展Exception类,使其成为选中的异常。异常类与任何其他类一样,包含有用的字段和方法。

//File Name InsufficientFundsException.java
import java.io.*;

public class InsufficientFundsException extends Exception { private double amount;

public InsufficientFundsException(double amount) { this.amount = amount; }

public double getAmount() { return amount; } }

为了演示如何使用用户自定义的异常,下面的CheckingAccount类包含了一个withage()方法,该方法抛出InassessentFundsException。

//File Name CheckingAccount.java
import java.io.*;

public class CheckingAccount { 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程序演示了如何调用CheckingAccount的Present()和without()方法。

//File Name 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);

  </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
     </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"\nWithdrawing $100..."</span><span class="pun">);</span><span class="pln">
     c</span><span class="pun">.</span><span class="pln">withdraw</span><span class="pun">(</span><span class="lit">100.00</span><span class="pun">);</span><span class="pln">
     </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"\nWithdrawing $600..."</span><span class="pun">);</span><span class="pln">
     c</span><span class="pun">.</span><span class="pln">withdraw</span><span class="pun">(</span><span class="lit">600.00</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">InsufficientFundsException</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
     </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Sorry, but you are short $"</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">getAmount</span><span class="pun">());</span><span class="pln">
     e</span><span class="pun">.</span><span class="pln">printStackTrace</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

} }

这将产生以下输出-

Depositing $500...

Withdrawing $100...

Withdrawing 600</span><spanclass="pun">...</span><spanclass="pln"></span><spanclass="typ">Sorry</span><spanclass="pun">,</span><spanclass="pln">butyouare</span><spanclass="kwd">short</span><spanclass="pln">600</span><span class="pun">...</span><span class="pln"> </span><span class="typ">Sorry</span><span class="pun">,</span><span class="pln"> but you are </span><span class="kwd">short</span><span class="pln"> 200.0 InsufficientFundsException at CheckingAccount.withdraw(CheckingAccount.java:25) at BankDemo.main(BankDemo.java:13)

参考链接

www.learnfk.com/java/java-e…