Java异常处理

本文深入讲解Java异常处理机制,包括异常的基本概念、异常类的分类、常见异常类型及处理方式。并通过实例演示如何使用try-catch-finally语句进行异常捕获与处理,以及如何自定义异常。

Java异常处理概述

异常是指程序在运行过程中出现的不正常情况或错误。这些错误的发生将阻止程序的正常运行。
异常发生的原因有很多,通常包括:

用户输入了非法数据。
要打开的文件不存在。
网络通信是连接中断或者JVM内存溢出。

这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其他一些是因为物理错误引起的。

Java异常处理机制

在一个方法的运行过程中,如果发生了异常:
①方法生成一个代表该异常的对象并把它提交给运行时系统,系统寻找相应的代码来处理这一个异常。把生成异常对象并把它提交给运行时系统的过程称为抛出一个异常(throw)
②运行时系统寻找相应的代码来处理这一异常,系统在方法的调用栈中查找,从产生异常的方法开始进行回溯,沿被调用的顺序往前寻找,直到找到包含相应异常处理的方法为止。这个过程称为捕获一个异常。
③如果该异常没有成功捕获,则程序将终止运行。一旦一个异常被抛出,它必须被一个异常处理程序捕获并且被立即处理。任何不是被子集程序捕获的异常最终都会被系统的默认处理程序处理。

class Exc2 {
    public static void main(String []args) {
        int d,a;
        try {
            d = 0;
            a = 42/d;
        }
        catch(ArithmeticException e) {
            System.out.println("Division by Zero.");
        }
        System.out.println("After catch statement.");
    }
}

异常类

Java的异常是一个对象。所有的异常都直接或者间接地继承Throwable类。
java.lang.Throwable是所有异常的超类
java.lang.Throwable有两个子类:java.lang.Error和java.lang.Exception
Error类及其子类由java虚拟机生成并抛出,包括动态链接失败,虚拟机错误等。Java程序通常不捕获错误。错误一般发生在严重故障时。
Exception类及其子类代表Java程序中可能发生的异常,并且应用程序可以捕获这些异常。
这里写图片描述
Java将异常分为两种类型,检查性异常非检查性异常(运行时异常)
如果由检查性异常程序不会通过编译,运行时异常程序中可以不做处理,直接由运行时系统来处理。编译器要求Java程序必须捕获或声明所有的编译时异常。

常见异常

Java定义了一些异常类在java.lang标准包中。

ArithmeticException

当出现异常的运算条件时,抛出此异常。例如,一个整数”除以零”时,抛出此类的一个实例。

ArrayIndexOutOfBoundsException

用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。

ArrayStoreException

试图将错误类型的对象存储到一个对象数组时抛出的异常。

ClassCastException

当试图将对象强制转换为不是实例的子类时,抛出该异常。

IllegalArgumentException

抛出的异常表明向方法传递了一个不合法或不正确的参数。

IllegalMonitorStateException

抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。

IllegalStateException

在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。

IllegalThreadStateException

线程没有处于请求操作所要求的适当状态时抛出的异常。

IndexOutOfBoundsException

指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。

NegativeArraySizeException

如果应用程序试图创建大小为负的数组,则抛出该异常。

NullPointerException

当应用程序试图在需要对象的地方使用 null 时,抛出该异常

NumberFormatException

当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。

SecurityException

由安全管理器抛出的异常,指示存在安全侵犯。

StringIndexOutOfBoundsException

此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。

UnsupportedOperationException

当不支持请求的操作时,抛出该异常。

Throwable类主要方法

public String getMessage() //返回关于发生的异常的详细信息
public Throwable getCause() //返回一个Throwable对象代表异常原因
public String toString() //使用getMessage()的结果返回类的串级名字
public void printStackTrace() //打印toString()结果和栈层次到System.err 即错误输出流

捕获异常

Java的异常处理是通过try catch 和finally 语句来实现的
try catch中的代码称为保护代码

try {
    ...程序代码
}
catch(ExceptionName e1) {
    ...捕获了e1异常
}
...
finally {
    ...最终处理
}

Catch语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try后面的catch块就会被检查。如果发生的异常包含在catch块中,异常就会被传递要该catch块。

选择catch语句时一般应该按照try代码块中异常可能产生的顺序及其真正类型进行捕获和处理。

当用多个catch语句时需要记住,异常子类必须在它们任何父类之前使用。

finally语句无论如何都会被执行。它提供了统一的出口。
在finally语句中可以运行清理类型等收尾善后性质的语句。
注意:finally try catch 语句之间不能存在任何代码!~

Demo:

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

抛出异常

如果一个方法没有捕获一个检查性异常,那么该方法必须使用throws关键字来声明。throws关键字放在方法签名的尾部。

throw关键字也可以抛出一个异常,无论是新实例化的还是刚捕获到的。
如抛出一个RemoteException异常:

import java.io.*;
public class className {
    public void deposit(double amount) throws RemoteException {
        throw new RemoteException();
    }
}

也可以声明抛出多个异常,多个异常之间用逗号隔开。

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

①在try中调用一个方法时,被调用方法中抛出了异常,则此被调用方法被中断执行,try块也被立即中断执行。
②处理异常的catch块必须紧跟在try块滞后
③如果一个catch块中定义的异常类型和程序抛出的异常类型匹配,则该程序立即被终止执行。
Demo

//JavaThrows.java
import java.io.*;
class JavaThrows {
    public int compute(int x) throws ArithmeticException {
        int z = 100/x;
        return z;
    }
    public void method1() {
        int x;
        try {
            x = System.in.read();
            x = x-48;
            x = compute(x);
            System.out.println(x);
        }
        catch(IOException ioe) {
            System.out.println("read error");
        }
        catch(ArithmeticException e) {
            System.out.println("devided by 0");
        }
    }
    public static void main(String []args) {
        JavaThrows t1 = new JavaThrows();
        t1.method1();
    }
}

自定义异常

Java中可以自己定义异常。编写异常类需要记住下面几点
①所有异常都必须是Throwable的子类
②如果希望写一个检查时异常类(即卡编译),则需要继承Exception类
③如果希望写一个运行时异常类,需要继承RuntimeException类

可以这样定义自己的异常类

class MyException extends Exception {
}

自定义异常类必须继承自Throwable或Exception类,建议用Exception类。自定义异常同样要用try-catch-finally形式捕获处理,但异常对象必须由用户自己抛出。

如下面的InsufficientFundsException类 继承自Exception

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

Demo:使用自定义异常类

//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.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("\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.0
InsufficientFundsException
        at CheckingAccount.withdraw(CheckingAccount.java:25)
        at BankDemo.main(BankDemo.java:13)

demo2:计算两个数的和,当任意一个数超出范围(10,20)时,抛出自己的异常

//NewException.java
//声明一个新的异常
class NumberRangeException extends Exception {
    public NumberRangeException(String msg) {
        super(msg);
    }
}

//捕获异常的主类
public class NewException {
    public int CalcAnswer(String str1,String str2) throws NumberRangeException {
        int int1,int2;
        int answer = -1;
        try {
            int1 = Integer.parseInt(str1);
            int2 = Integer.parseInt(str2);
            if(int1 < 10 || int2 < 10 || int1 > 20 || int2 > 20) {
                NumberRangeException e = new NumberRangeException("Numbers are not within the specified range.");
                throw e;
            }
            answer = int1 + int2;
        }
        catch(NumberFormatException e) {
            System.out.println(e.toString());
        }
        return answer;
    }
    public void getAnswer() {
        String answerStr;
        try {
            int answer = CalcAnswer("12","5");
            answerStr = String.valueOf(answer);
        }
        catch(NumberRangeException e) {
            answerStr = e.getMessage();
        }
        System.out.println(answerStr);
    }
    public static void main(String []args) {
        NewException t1 = new NewException();
        t1.getAnswer();
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值