Java异常处理

基础技术、技术与框架Java异常处理插图
异常处理原理图

1、前言:什么是异常处理机制?

我们先从例子来引入Java的异常处理机制。

package com.company;

import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        /* 定义一个长度10的 数组*/
        int[] a = new int[10];
        int idx;
        /*用户输入数字*/
        System.out.println("Please Entry number:");
        Scanner in = new Scanner(System.in);
        idx = in.nextInt();
        /*
        定义a[x],当用户输入x时,则输出x
        但因为定义的数组长度10,所以用户输入[0~9]以外会报错
        * */
        a[idx]=idx;
        System.out.println("User Entry:"+a[idx]);
    }
}

通过上述例子,我们不难看出,当用户输入【0~9】以外的数,就会报错。那如何处理这种异常呢?

Java把可能发生错误的异常放在try;把处理异常的方法写在catch中。

package com.company;

import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        /* 定义一个长度10的 数组*/
        int[] a = new int[10];
        int idx;
        /*用户输入数字*/
        System.out.println("Please Entry number:");
        Scanner in = new Scanner(System.in);
        idx = in.nextInt();
        /*
        定义a[x],当用户输入x时,则输出x
        但因为定义的数组长度10,所以用户输入[0~9]以外会报错
        * */
        try {
            a[idx] = idx;
            System.out.println("User Entry:" + a[idx]);
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("User Entry error");
        }
    }
}
基础技术、技术与框架Java异常处理插图1

2、try-catch案例

package com.company;

import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;

import java.util.Scanner;

public class Main {
    public static void fa() {
        int a[] = new int[2];
        a[2]=1;
        /* 遇到异常后下面的代码不执行  */
        System.out.println("hello1");

    }
    public static void main(String[] args) {
            // TODO Auto-generated method stub
        try {
            fa();
            System.out.println("hello2");
        } catch (ArrayIndexOutOfBoundsException e) {
            // TODO: handle exception
            System.out.println("catch");
        }
        /*
        如果catch能匹配到的话,执行下面的代码,如何执行不到则报错
        例如把上面的catch换成例如把上面的catch换成NullPointerException
        */
        System.out.println("hello3");
    }

}
基础技术、技术与框架Java异常处理插图2

e.getMessage()获取是哪个错误

e.printStackTrace();获取异常堆栈,根据堆栈从下往上追溯

package com.company;

import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;

import java.util.Scanner;

public class Main {
    public static void fa() {
        int a[] = new int[2];
        a[2]=1;
        /* 遇到异常后下面的代码不执行  */
        System.out.println("hello1");
    }
    public static void main(String[] args) {
            
        try {
            fa();
            System.out.println("hello2");
        } catch (ArrayIndexOutOfBoundsException e) {
            // TODO: handle exception
            System.out.println("catch");
            System.out.println(e.getMessage());
            System.out.println(e.toString());
            e.printStackTrace();
        }
        /*
        如果catch能匹配到的话,执行下面的代码,如何执行不到则报错
        例如把上面的catch换成例如把上面的catch换成NullPointerException
        */
        System.out.println("hello3");
    }

}
基础技术、技术与框架Java异常处理插图3

3、throw e;再次抛出

package com.company;

import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;

import java.util.Scanner;

public class Main {
    public static void fa() {
        int a[] = new int[2];
        a[2]=1;
        /* 遇到异常后下面的代码不执行  */
        System.out.println("hello1");
    }

    public static void  aaa(){
        try{
            fa();
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("catch1");
        }

    }
    public static void main(String[] args) {

        try {
            aaa();
            System.out.println("hello2");
        } catch (ArrayIndexOutOfBoundsException e) {
            // TODO: handle exception
            System.out.println("catch2");
        }
        /*
        如果catch能匹配到的话,执行下面的代码,如何执行不到则报错
        例如把上面的catch换成例如把上面的catch换成NullPointerException
        */
        System.out.println("hello3");
    }
}
基础技术、技术与框架Java异常处理插图4

根据上述代码,我们不难发现,如果被一次catch匹配后,后面的catch就不会执行【catch2不输出】,如果我们需要catch2也要输出,那应该如何处理?

package com.company;

import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;

import java.util.Scanner;

public class Main {
    public static void fa() {
        int a[] = new int[2];
        a[2]=1;
        /* 遇到异常后下面的代码不执行  */
        System.out.println("hello1");
    }

    public static void  aaa(){
        try{
            fa();
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("catch1");
            throw e;
        }
    }
    public static void main(String[] args) {

        try {
            aaa();
            System.out.println("hello2");
        } catch (ArrayIndexOutOfBoundsException e) {
            // TODO: handle exception
            System.out.println("catch2");
        }
        /*
        如果catch能匹配到的话,执行下面的代码,如何执行不到则报错
        例如把上面的catch换成例如把上面的catch换成NullPointerException
        */
        System.out.println("hello3");
    }
}
基础技术、技术与框架Java异常处理插图5

结果显示:catch1和catch2的异常都抛出了,但注意【hello2】不输出

4、finally跳出异常前执行

package com.company;

import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;

import java.util.Scanner;

public class Main {
    public static void fa() {
        int a[] = new int[2];
        a[2]=1;
        /* 遇到异常后下面的代码不执行  */
        System.out.println("hello1");
    }

    public static void  aaa(){
        try{
            fa();
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("catch1");
            throw e;
        }
    }
    public static void main(String[] args) {

        try {
            aaa();
            System.out.println("hello2");
        } catch (ArrayIndexOutOfBoundsException e) {
            // TODO: handle exception
            System.out.println("catch2");
        }
        finally {
            System.out.println("插入日志");
        }
        /*
        如果catch能匹配到的话,执行下面的代码,如何执行不到则报错
        例如把上面的catch换成例如把上面的catch换成NullPointerException
        */
        System.out.println("hello3");
    }
}
基础技术、技术与框架Java异常处理插图6

5、如何进行自定义异常

先创建InsufficientFundsException.java

package catchtest;
 import java.io.*;
 public class InsufficientFundsException extends Exception
 {
   //此处的amount用来储存当出现异常(取出钱多于余额时)所缺乏的钱
   private double amount;
   public InsufficientFundsException(double amount)
   {
     this.amount = amount;
   } 
   public double getAmount()
   {
     return amount;
   }
 }

创建CheckingAccount.java

package catchtest;

import java.util.Scanner;

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;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		CheckingAccount c = new CheckingAccount(101);
	    System.out.println("存入: $500...");
	    c.deposit(500.00);
	    System.out.println("您的余额:"+c.getBalance());
	    
	    
        try {
        	Scanner in = new Scanner(System.in);
        	Double Double1 = Double.valueOf(in.nextLine().toString());
        	System.out.println("\n正在取出"+Double1);
			c.withdraw(Double1);
		} catch (InsufficientFundsException e) {
			// TODO Auto-generated catch block
			System.out.println("Sorry, 你还差 $"
                    + e.getAmount());
			
		} catch (Exception e){
			
			e.printStackTrace();
		}finally {
			System.out.println("您的余额:"+c.getBalance());
		}
	}

}