开发手册 欢迎您!
软件开发者资料库

Java - 例外

Java异常 - 从简单和简单的步骤学习Java从基本到高级概念,包括Java语法面向对象语言,方法,覆盖,继承,多态,接口,包,集合,网络,多线程,泛型,多媒体,序列化,GUI 。

异常(或异常事件)是在执行程序期间出现的问题.当发生异常时,程序的正常流程中断,程序/应用程序异常终止,这是不推荐的,因此,这些异常将被处理.

由于许多不同的原因,可能会发生异常.以下是发生异常的一些情况.

  • 用户输入了无效数据.

  • 找不到需要打开的文件.

  • 网络连接丢失了通信或JVM内存不足.

其中一些异常是由用户错误引起的,其他异常是由程序员错误引起的,还有其他异常引起的通过以某种方式失败的物理资源.

基于这些,我们有三类例外.您需要了解它们以了解异常处理如何在Java中工作.

  • 检查异常&minus ;已检查的异常是编译器在编译时检查(通知)的异常,这些异常也称为编译时异常.这些异常不能简单地被忽略,程序员应该处理(处理)这些异常.

例如,如果你使用 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.javaFilenotFound_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.

  • 未经检查的例外 : 未经检查的异常是在执行时发生的异常.这些也称为运行时异常.这些包括编程错误,例如逻辑错误或API的不当使用.编译时忽略运行时异常.

例如,如果在程序中声明了一个大小为5的数组,并且试图调用数组的6 th 元素,然后发生 ArrayIndexOutOfBoundsExceptionexception .

示例

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: 5at Exceptions.Unchecked_Demo.main(Unchecked_Demo.java:8)

  • 错误 : 这些都不是例外,而是超出用户或程序员控制的问题.代码中通常会忽略错误,因为您很少对错误做任何事情.例如,如果发生堆栈溢出,则会出现错误.它们在编译时也被忽略.

异常层次结构

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

错误是在严重失败的情况下发生的异常情况,Java程序无法处理这些异常情况.生成错误以指示运行时环境生成的错误.示例:JVM内存不足.通常,程序无法从错误中恢复.

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

Exceptions1

以下是最常见的已检查和未检查的列表Java的内置异常.

异常方法

以下是Throwable类中可用的重要方法列表.

Sr.No.Method&说明
1

public String getMessage()

返回有关已发生异常的详细消息.此消息在Throwable构造函数中初始化.

2

public Throwable getCause()

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

3

public String toString()

返回与getMessage()结果连接的类的名称.

4

public void printStackTrace()

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

5

public StackTraceElement [ ] getStackTrace()

返回包含堆栈跟踪上每个元素的数组.索引0处的元素表示调用堆栈的顶部,数组中的最后一个元素表示调用堆栈底部的方法.

6

public Throwable fillInStackTrace()

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

捕获异常

使用try/catch

语法

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

容易出现异常的代码放在try块中.发生异常时,发生的异常由与其关联的catch块处理.每个try块都应该紧跟一个catch块或者最后一个块.

一个catch语句涉及声明你想要捕获的异常类型.如果受保护代码中发生异常,则会检查try之后的catch块(或多个块).如果发生的异常类型列在catch块中,则将异常传递给catch块,就像将参数传递给方法参数一样.

示例

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

// File Name : ExcepTest.javaimport 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: 3Out of the block

多个捕获块

try块后面可以跟多个catch块.多个catch块的语法类似于以下 :

语法

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

前面的语句演示了三个catch块,但是你可以有任意数量的他们经过一次尝试.如果受保护代码中发生异常,则会将异常抛出到列表中的第一个catch块.如果抛出的异常的数据类型与ExceptionType1匹配,则会在那里捕获它.如果不是,则异常传递给第二个catch语句.这种情况一直持续到异常被捕获或落入所有捕获,在这种情况下,当前方法停止执行,并且异常被抛到调用堆栈上的前一个方法.

示例

以下是显示如何使用多个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;}

捕获多种类型的异常

从Java 7开始,您可以处理多个异常使用单个catch块,此功能简化了代码.以下是你将如何做:

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

抛出/抛出关键字

如果方法不处理已检查的异常,则该方法必须使用 throws 关键字. throws关键字出现在方法签名的末尾.

您可以使用 throw

尝试理解throws和throw关键字之间的区别, throws 用于推迟处理已检查的异常并抛出用于显式调用异常.

以下方法声明它抛出RemoteException :

示例

import java.io.*;public class className {   public void deposit(double amount) throws RemoteException {      // Method implementation      throw new RemoteException();   }   // Remainder of class definition}

方法可以声明它抛出多个异常,在这种情况下,异常在以逗号分隔的列表中声明.例如,以下方法声明它抛出RemoteException和InsufficientFundsException :

示例

import java.io.*;public class className {   public void withdraw(double amount) throws RemoteException,       InsufficientFundsException {      // Method implementation   }   // Remainder of class definition}

The Finally Block

finally块遵循try块或者一个陷阱.无论发生异常,最终都会执行最后一段代码.

使用finally块可以运行任何要执行的清理类型语句,无论发生什么受保护的代码.

最后一个块出现在catch块的末尾,并具有以下语法 :

语法

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

示例

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: 3First element value: 6The finally statement is executed

请注意以下 :

  • 一个catch子句没有try语句就不能存在.

  • 每当有try/catch块时,不必强制终止子句.

  • 如果没有catch子句或finally子句,则try块不能出现.

  • 任何代码都不能出现在尝试,捕获,最后阻止.

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);   // reads the content to the array         for(char c : a)         System.out.print(c);   // prints the characters one by one      } catch (IOException e) {         e.printStackTrace();      }finally {         try {            fr.close();         } catch (IOException ex) {            ex.printStackTrace();         }      }   }}

试用资源 ,也称为自动资源管理,是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);   // reads the contentto the array         for(char c : a)         System.out.print(c);   // prints the characters one by one      } catch (IOException e) {         e.printStackTrace();      }   }}

在使用try-with-resources语句时,请记住以下几点.

  • 要使用带有try-with-resources语句的类,它应该实现 AutoCloseable 接口并且它的 close()方法在运行时自动调用.

  • 你可以在try-with中声明多个类-resources statement.

  • 当你在try-with-resources语句的try块中声明多个类时,这些类会以相反的顺序关闭.

  • 除了括号内的资源声明外,一切都与try块的普通try/catch块相同.

  • try中声明的资源在try-block开始之前实例化.

  • 在try块声明的资源是隐式声明的作为最终.

用户定义的例外

您可以在Java中创建自己的异常.在编写自己的例外类和减号时,请记住以下几点;

  • 所有例外必须是Throwable的子项.

  • 如果要编写由Handle或Declare Rule自动强制执行的已检查异常,则需要扩展Exception类.

  • 如果要编写运行时异常,则需要扩展RuntimeException类.

我们可以将我们自己的Exception类定义为下面和下面;

class MyException extends Exception {}

您只需要扩展预定义的 Exception 类来创建自己的Exception.这些被认为是经过检查的例外.以下 InsufficientFundsException 类是一个用户定义的异常,它扩展了Exception类,使其成为一个已检查的异常.异常类与任何其他类一样,包含有用的字段和方法.

示例

// File Name InsufficientFundsException.javaimport java.io.*;public class InsufficientFundsException extends Exception {   private double amount;      public InsufficientFundsException(double amount) {      this.amount = amount;   }      public double getAmount() {      return amount;   }}

为了演示使用我们的用户定义的异常,以下CheckingAccount类包含一个throw()方法,它抛出一个InsufficientFundsException.

// File Name CheckingAccount.javaimport 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的deposit()和withdraw()方法.

// File Name BankDemo.javapublic 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();      }   }}

编译以上三个文件并运行BankDemo.这将产生以下结果 :

输出

Depositing $500...Withdrawing $100...Withdrawing $600...Sorry, but you are short $200.0InsufficientFundsException         at CheckingAccount.withdraw(CheckingAccount.java:25)         at BankDemo.main(BankDemo.java:13)

常见异常

在Java中,它是可以定义两个例外和错误的分类.

  • JVM异常 : 这些是JVM专门或逻辑抛出的异常/错误.示例:NullPointerException,ArrayIndexOutOfBoundsException,ClassCastException.

  • 程序化异常 : 应用程序或API程序员明确抛出这些异常.示例:IllegalArgumentException,IllegalStateException.