zoukankan      html  css  js  c++  java
  • Java的异常处理

    以下内容引用自http://wiki.jikexueyuan.com/project/java/exceptions.html

    异常是一个程序执行过程中出现的问题。引起异常的原因包括以下几点:

    • 用户输入无效的数据
    • 用户打开一个不能被找到的文件
    • 网络连接已经丢失或JVM已经耗尽内存

    一些异常是由于用户的错误,也有是因为程序员的错误,还有是因为一些物理资源在某些形式上的错误。

    在Java中了解异常处理,需要了解异常的三个类别:

    • 检测异常(Checked exceptions:一个已检测异常通常是用户错误或是一个程序员不能预见的错误,如果一个文件将要被打开,但系统找不到这个文件,异常就会发生。这些异常在编译时不能被简单忽略。
    • 运行时异常(Runtime Exceptions):运行时异常是可以被程序语法避免的。不同于检测异常,运行时异常在编译时可以被忽略。
    • 错误(Errors):这并不是异常,但这不是用户或程序员可以控制的。错误经常在代码中被忽略,因为针对一个错误几乎做不了任何事。比如,如果一个堆栈溢出发生时,将会出现一个错误。他们在编译时也会被忽略。

    一、异常的层次结构

    所有的异常类都是java.lang.Exception类的子类型。异常类都是Throwable类的子类。除了异常类Error类也是由Throwable类产生的的子类。

    错误一般不会由Java程序解决。这些条件通常是在Java程序解决不了的错误出现时才会发生。 Errors用来去指示那些运行时环境生成的错误。举例说明:JVM(java虚拟机)是不在内存中的。一般程序不能从错误中恢复。

    Exception类含有两个子类:IOException类和RuntimeException类。

    二、异常方法

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

    方法描述
    public String getMessage()  返回关于发生异常的细节信息,这些信息在Throwable的构造函数中被初始化
    public Throwable getCause()  返回发生异常的原因,由Throwable对象来表示
    public String toString()  返回与getMessage()的结果相联系的类的名称
    public void printStackTrace()  打印toString()跟踪错误输出流的栈地址的结果。
    public StackTraceElement [] getStackTrace()  返回一个数组,其中包含每个元素在栈的地址。元素的索引0代表调用栈的顶部,最后一个元素表示方法调用栈的底部。
    public Throwable fillInStackTrace()  用当前栈地址来填充Throwable对象的栈地址,添加到任何先前的栈地址信息。

    三、捕获异常

    一个方法用关键字try和catch来捕获异常。一个try/catch块放置在可能产生异常的代码外。在try/catch块内的代码是被保护的,并且其语法如下:

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

    关于catch的声明,必须要指明捕获的异常的类型。如果受保护的代码中发生异常,跟在try后面的catch块会被检测。如果异常类型在catch中出现了,那么这个异常会被传递到catch当中,就像实参传递到方法参数当中。

    示例:

    下面的例子声明了一个含有两个元素的数组。然后代码试图访问数组的第三个元素,这将抛出一个异常。

    // 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

    四、多个catch块

    一个try块可以有多个catch块。多个catch块的语法如下:

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

    前面的语句演示三个catch块,但是可以在一个try后面跟任意数量的catch块。当被保护代码中出现异常时,异常首先会被第一个catch块抓住,如果该异常类型在第一个catch块中列出,便在第一个catch块中被捕获。如果没有列出,便依次向下一个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;
    }

    五、throws/throw关键词

    如果一个方法不能处理检测异常,那么该方法必须用关键字throws来声明。throws关键字在方法名的最后出现。

    可以通过关键字throw来抛出一个异常或进行刚捕获到的异常的实例化。

    以下方法声明它抛出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
    }

    提示:throw用于抛出异常,throws用于告诉调用此方法的方法需要处理这个异常,同样throws可以在调用的方法中不用处理,直接throws给上一层,知道给JVM去处理。

    六、关键字finally

    finally关键字用于创建跟在try后面的代码块,finally代码块总是会被执行的,不管是怎样的异常发生。

    使用finally块允许运行想要执行的任何cleanup-type语句,无论在受保护的代码中发生什么。

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

    以下几点需要注意:

    • catch在没有try关键字的情况下是不能够出现的。
    • try/catch语句块中并不是强制出现finally块。
    • try语句块不能独立存在(即没有任何catch和finally块)。
    • 在try/catch和finally块之间是不能出现任何代码的。

    七、声明自己的异常

    可以在Java中创建自己的异常。编写自己的异常类,要记住以下几点:

    • 所有的异常必须Throwable的子类。
    • 如果想写一个自动遵守正确处理或声明规则的检测异常,需要继承Exception 类。
    • 如果想编写一个运行时异常,需要继承RuntimeException类。

    如下可以定义自己的异常类:

    class MyException extends Exception{
    }

    只需要继承Exception类来创建自己的异常类。这些被认为是检测异常。以下InsufficientFundsException类是一个用户定义的异常,同样继承了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类包含一个withdraw()方法抛出了一个InsufficientFundsException异常。

    // 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的deposit()和withdraw()方法。

    // 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);
          try
          {
             System.out.println("
    Withdrawing $100...");
             c.withdraw(100.00);
             System.out.println("
    Withdrawing $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.0
    InsufficientFundsException
            at CheckingAccount.withdraw(CheckingAccount.java:25)
            at BankDemo.main(BankDemo.java:13)

    八、常见的异常

    在Java中,可以定义两种异常和错误

    • JVM异常:这些异常/错误是由JVM在逻辑层上或专门抛出的。例如:NullPointerException,ArrayIndexOutOfBoundsException,ClassCastException。
    • 程序性异常:这些异常是由应用程序或是编写API的程序员明确抛出的,例如:IllegalArgumentException,IllegalStateException。

    测试工程:https://github.com/easonjim/5_java_example/tree/master/javabasicstest/test15

  • 相关阅读:
    easyui validatebox textbox 取值和赋值
    linq中如何在join中指定多个条件
    easyui datagrid 表头固定(垂直滚动条)、列固定(水平滚动条)
    JS Jquery 中 的遍历
    EasyUI datagrid formatter 属性
    基于C#的socket编程的TCP异步实现
    Winform 最小化双击显示,最小化右键退出。退出
    C#中的Invoke
    Socket之listen() receive()
    20210512学习笔记--一直没干啥有用的事儿,最主要还是量变不够,进展过于慢了
  • 原文地址:https://www.cnblogs.com/EasonJim/p/6935119.html
Copyright © 2011-2022 走看看