Java 异常处理

作者: TryEnough | 来源:发表于2019-01-02 16:42 被阅读3次

原文链接


Java 异常处理


你将学到

  • Java中异常的捕获方法

  • throws/throwfinally 关键字

  • Java中常见的异常

  • Java中异常类层次结构

  • 常见的异常错误的使用方式

  • 自定义异常的方法


Java中异常的捕获方法


语法:

try {
   // 可能发生异常的程序代码
}catch(ExceptionName e) {
   //捕获到名为ExceptionName的异常的处理代码
}

<table><tr><td bgcolor=#D1EEEE> 解释:<font color="#dd0000"> try </font> 部分包裹着可能发生异常的代码,可以保护程序发生异常时不突然结束,而是被<font color="#dd0000"> catch </font>部分捕获到异常,从而让程序员有机会处理这个异常,保证程序继续走下去。</td></tr></table>

举例:

public class Main {
    public static void main(String[] args) {
        try {
            int[] data = new int[]{1,2,3};
            getDataByIndex(-1,data);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
 
    }
 
    public static int getDataByIndex(int index,int[] data) {
        if(index<0||index>=data.length)
            throw new ArrayIndexOutOfBoundsException("数组下标越界");
        return data[index];
    }
}

在上面的例子中,当数组越界的时候方法getDataByIndex会抛出异常,因为我们在main方法中用try...catch包裹了这个方法的调用,所以当异常发生时,main方法中的catch就会捕获到这个异常,这里的处理方式是将异常打印到控制台(开发中debug阶段经常用这种方式来调试代码,但是,realse阶段需要将异常写入日志)。

throws/throw和 finally 关键字


<font color="#000000">throw 关键字</font><br />
上例中我们已经在getDataByIndex方法中用到了throw关键字来抛出一个异常。

在写代码时,如果某些情况下不允许程序继续走下去,就可以像上面一样,抛出一个异常给调用者,以便调用者知道发生了异常,并对异常情况进行处理。

<font color="#000000">throws 关键字</font><br />
上面的例子是主动抛出异常(throw表示直接抛出异常),但是某些情况下我们希望表达某个方法有可能发生异常,可以用throws关键字。

举例:

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

表示withdraw方法可能抛出RemoteException或者InsufficientFundsException两种异常。如果调用这样一个方法,Java编译机会要求调用者添加try...catch的代码来捕获异常,而这里有可能发生两种异常,我们可以使用多重捕获块:

try{
   // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}

<font color="#000000">finally 关键字</font><br />

无论是否发生异常,都希望执行的代码,可以放在finally关键子块里:

语法:

try{
  // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}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

Java中常见的异常


<table><tr><td bgcolor=#D8D8D8>运行时异常</td></tr></table>

异常名 异常解析
ArrayIndexOutOfBoundException 数组索引越界异常
ArithmeticException 算术条件异常,如除数为0
NullPointException 空指针异常
ClassNotFoundException 找不到类异常
NegativeArraySizeException 数组长度为负异常
ArrayStoreException 数组中包含不兼容的值抛出异常
SecurityException 安全性异常
IllegalArgumentException 非法参数异常

<table><tr><td bgcolor=#D8D8D8>IOException</td></tr></table>

异常名 异常解析
IOException 操作输入流和输出流可能出现的异常
EOFException 文件已结束异常
FileNotFoundException 文件未找到异常

常见的异常绝非仅此而已,具体的只能使用的时候碰到再具体分析。

Java中异常类层次结构


系统的异常类层次分明

java异常结构

虽然结构看着很多,但是需要程序员处理的一般只有Exception类型的异常。因为Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程。

  • 运行时异常(非检查性异常):包括RuntimeException及其子类和Error。
  • 检查性异常:在编译时不能被简单地忽略,例如用户错误或问题引起的异常(如打开一个不存在文件时)。

异常错误的使用方式


<font color="#dd0000">选择异常</font><br />

1、是否需要立即终止。

2、是否需要进一步处理和恢复。

举例:

将 SQLException 定义为非检测异常(就是不需要立即停止的异常),这样操作数据时开发人员理所当然的认为 SQLException 不需要调用代码的显式捕捉和处理,进而会导致严重的 Connection 不关闭、Transaction 不回滚、DB 中出现脏数据等情况。

所以需要将 SQLException 定义为检测异常,才会驱使开发人员去显式捕捉,并且在代码产生异常后清理资源。

<font color="#dd0000">对代码层次结构的污染</font><br />

举例:

public Man retrieve(Long id) throw SQLException {
 //根据 ID 查询数据库
}

上面这段代码咋一看没什么问题,但是从设计耦合角度仔细考虑一下,这里的 SQLException 污染到了上层调用代码,调用层需要显式的利用 try-catch 捕捉,或者向更上层次进一步抛出。根据设计隔离原则,我们可以适当修改成:

public Man retrieve(Long id) {
     try{
            //根据 ID 查询数据库
     }catch(SQLException e){
            //利用非检测异常封装检测异常,降低层次耦合
            throw new RuntimeException(SQLErrorCode, e);
     }finally{
            //关闭连接,清理资源
     }
}

<font color="#dd0000">将异常包含在循环语句块中</font><br />

for(int i=0; i<100; i++){
    try{
    }catch(XXXException e){
         //….
    }
}

这么做最主要的问题在于是处理异常消耗系统资源太多。

<font color="#dd0000">利用 Exception 捕捉所有潜在的异常</font>

有时候懒得捕捉所有异常,就利用基类 Exception 捕捉所有潜在的异常:

public void retrieveObjectById(Long id){
    try{
        //…抛出 IOException 的代码调用
        //…抛出 SQLException 的代码调用
    }catch(Exception e){
        //这里利用基类 Exception 捕捉的所有潜在的异常,如果多个层次这样捕捉,会丢失原始异常的有效信息
        throw new RuntimeException(“Exception in retieveObjectById”, e);
    }
}

这么做的坏处是:丢失了发生其他异常的具体信息。

<font color="#dd0000">在你的方法里抛出不具体的检查性异常</font>

public void foo() throws Exception { //错误方式
}

<font color="#dd0000">“早throw晚catch”原则</font>

应该尽快抛出(throw)异常,并尽可能晚地捕获(catch)它。 你应该等到你有足够的信息来妥善处理它。

自定义异常的方法


  • 如果希望写一个检查性异常类,则需要继承 Exception 类。
  • 如果希望写一个运行时异常类,那么需要继承 RuntimeException 类。
class MyException extends Exception{
}

举例:

class MyException extends Exception {
    private int detail;
    MyException(int a){
        detail = a;
    }
    public String toString(){
        return "MyException ["+ detail + "]";
    }
}
public class TestMyException{
    static void compute(int a) throws MyException{
        System.out.println("Called compute(" + a + ")");
        if(a > 10){
            throw new MyException(a);
        }
        System.out.println("Normal exit!");
    }
    public static void main(String [] args){
        try{
            compute(1);
            compute(20);
        }catch(MyException me){
            System.out.println("Caught " + me);
        }
    }
}

运行结果:

Called compute(1)

Normal exit!

Called compute(20)

Caught MyException [20]

相关文章

  • Java- 异常处理

    Java- 异常处理 异常处理能够使一个方法给它的调用者抛出一个异常。 Java异常是派生自 java.lang....

  • JNI异常

    JNI异常 JNI允许native方法引发任意Java异常。native代码还可以处理未解决的Java异常。未处理...

  • Java 异常分析

    本文是对以下内容的分析: Java异常设计 Java 异常分类 Java异常可以告诉什么问题 Java异常处理最佳...

  • Java异常处理-检查性异常、非检查性异常、Error

    一、Java异常处理详解 Java异常处理-笔记中的@doublefan讲解得非常通熟易懂 二、检查型异常和非检查...

  • java异常---异常处理

    一、重点知识 IDEA创建配置文件file目录下选择Resource Bundle,直接输入文件名创建就好了 记得...

  • Java基础系列-Exception异常处理

    原创文章,转载请标注出处:《Java基础系列-Exception异常处理》 一、概述 Java代码中的异常处理是非...

  • 04- JAVA异常

    在JAVA中异常就是一个类,产生异常就是创建异常对象并抛出一个异常对象。JAVA处理异常的方式是中断处理。参考:j...

  • Kotlin2.5异常

    Kotlin的异常处理和Java以及其他许多语言的处理方式相似,异常处理语句的基本形式和Java类似,抛出异常的方...

  • Java自学-异常处理 处理

    Java的异常处理办法 try catch throws 异常处理常见手段: try catch finally ...

  • Java 异常面试问题与解答

    Java 提供了一种健壮且面向对象的方法来处理称为 Java异常处理的异常情况。 1. Java中的异常是什么? ...

网友评论

    本文标题:Java 异常处理

    本文链接:https://www.haomeiwen.com/subject/feozlqtx.html