Java中对于异常的处理和使用

        在理想世界中,用户输入数据的格式永远正确,选择打开的文件也一定存在,代码永远不会出现bug。但在现实世界中却充满了不良的数据和有问题的代码,试想一下如果费劲心思写完了一个非常冗杂的代码,但是却出现了不间断的异常,是多么的感到不适。这时我们就需要了解自己的代码,对可能出现的bug和错误加以提示,以便后来的调试与修改。在Java中提供了一些官方的异常申明,当然也可以自定义异常并且加以处理,下面详细说明一下我对于异常的理解和看法。

一:异常的概念:

                在Java中,将程序执⾏过程中发⽣的不正常⾏为称为异常,下面举几个例子说明:

1.算数异常

public static void main(String[] args) {
System.out.println(10 / 0);
}

运行时出现:

2.数组越界异常:

public static void main(String[] args) {
int[] array = {1, 2, 3};
System.out.println(array [100]);
}

运行时的结果:

        从以上的结果可以看出Java中的每一种异常都有对应的类来表示出来。

二:异常的分类:

        在Java程序设计语言中异常对象都是派生于Throwable类的一个类的实例,如果Java中内置的异常类不能满足需求,用户还可以创建自己的异常类。

1. Throwable:是异常体系的顶层类,其派⽣出两个重要的⼦类, Error 和 Exception
2. Error:指的是Java虚拟机⽆法解决的严重问题,⽐如:JVM的内部错误、资源耗尽等,典型代
表:StackOverflowError和OutOfMemoryError,⼀旦发⽣回⼒乏术。
3. Exception:异常产⽣后程序员可以通过代码进⾏处理,使程序继续执⾏。⽐如:感冒、发烧。我 们平时所说的异常就是Exception。

······编译时异常:

        我们知道程序都是先编译后执行的,在程序的编译阶段出现的异常叫做编译时异常,也叫做受检查异常。(Checked Exception)

······执行时异常:

        在程序的执行过程中产生的异常叫做执行时异常,也叫做非受检查异常。(Unchecked Exception)

        在程序执⾏期间发⽣的异常,称为运⾏时异常,也称为⾮受检查异常(Unchecked Exception)
RunTimeException以及其⼦类对应的异常,都称为运⾏时异常。⽐如:NullPointerException、
ArrayIndexOutOfBoundsException、ArithmeticException。
        注意:编译时出现的语法性错误,不能称之为异常。例如将 System.out.println 拼写错了, 写成了 system.out.println. 此时编译过程中就会出错, 这是 "编译期" 出错。⽽运⾏时指的是程序已经编译通过得到 class ⽂件了, 再由 JVM 执⾏过程中出现的错误.

三:异常的处理:

 1.声明检查型异常:

        在声明时使用throws关键字,throws 关键字⽤于在⽅法声明中列出该⽅法可能抛出的异常,它告诉调⽤者这个⽅法可能会抛出某些异常,调⽤者需要处理这些异常。使⽤ throws 实际上是将异常的处理责任转移给了调⽤该⽅法的代码。

语法格式:
修饰符 返回值类型 ⽅法名 ( 参数列表 ) throws 异常类型 1 ,异常类型 2. ..{
}
实例代码如下:
/*
        FileNotFoundException : 编译时异常,表明⽂件不存在
        此处不处理,也没有能⼒处理,应该将错误信息报告给调⽤者,让调⽤者检查⽂件名字是否给错
        误了
        */
        public void OpenConfig(String filename) throws FileNotFoundException {
            if (filename.equals("config.ini")) {
                throw new FileNotFoundException("配置⽂件名字不对");
            }
            // 打开⽂件
        }

其中代码第一行就是使用throws关键词来对可能出现的异常的声明,代码第三行使用了throw关键字抛出了一个指定的异常用来提醒调用者。

注意:

1.声明的异常必须是 Exception 或者 Exception 的⼦类

2.⽅法内部如果抛出了多个异常,throws之后必须跟多个异常类型,之间⽤逗号隔开,如果抛出多个异常类型具有⽗⼦关系,直接声明⽗类即可。

3.调⽤声明抛出异常的⽅法时,如果该异常是编译时异常/受查异常时,调⽤者必须对该异常进⾏处 理,或者继续使⽤throws抛出。

在IDEA编译器中,对异常进行处理时可以使用alt+enter快捷键出现如上图所示两种处理结果

关于throw的用法,详见下列代码(实现⼀个获取数组中任意位置元素的⽅法。

public static int getElement(int[] array, int index){
    if(null == array){
        throw new NullPointerException("传递的数组为null");
    }
    if(index < 0 || index >= array.length){
        throw new ArrayIndexOutOfBoundsException("传递的数组下标越界");
    }
        return array[index];
}
public static void main(String[] args) {
    int[] array = {1,2,3};
    getElement(array, 3);
}

倒数第二行代码调用方法getElement时,很明显下标越界了,这时手动抛出了一个异常后编译器会识别出来:

        在程序设计时,一个方法必须声明所有可能抛出的检查型异常,而非检查型异常要么在你的控制之外,要么是由一开始就应该避免的情况导致的。

2.异常的真正处理(try-catch语句的用法)

在上述中throws对异常并没有真正处理,⽽是将异常报告给抛出异常⽅法的调⽤者,由调⽤者处理。如果真正要对异常进⾏处理,就需要try-catch语句来实现。只有真正的处理了异常,才不会在中间报出异常后干扰到后面程序的正常运行。
语法格式:
try{
// 将可能出现异常的代码放在这⾥
}catch(要捕获的异常类型 e){
// 如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型⼀致
时,或者是try中抛出异常的基类时,就会被捕获到
// 对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执⾏后序代码
}[catch(异常类型 e){
// 对异常进⾏处理
}finally{
// 此处代码⼀定会被执⾏到
}]
// 后序代码
// 当异常被捕获到时,异常就被处理了,这⾥的后序代码⼀定会执⾏
// 如果捕获了,由于捕获时类型不对,那就没有捕获到,这⾥的代码就不会被执⾏
注意:
1. []中表⽰可选项,可以添加,也可以不⽤添加
2. try中的代码可能会抛出异常,也可能不会
try中可能会抛出多个不同的异常对象,则必须⽤多个catch来捕获----即多种异常,多次捕获
如:
public static void main(String[] args) {
int[] array = {1, 2, 3};
try {
System.out.println("before");
// array = null;
System.out.println(array [100]);
System.out.println("after");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("这是个数组下标越界异常");
e.printStackTrace();
} catch (NullPointerException e) {
System.out.println("这是个空指针异常");
e.printStackTrace();
}
System.out.println("after try catch");
}

运行结果:

如果多个异常的处理⽅式是完全相同, 也可以写成这样:
catch (ArrayIndexOutOfBoundsException | NullPointerException e) {
...
}

如果异常之间具有⽗⼦关系,⼀定是⼦类异常在前catch,⽗类异常在后catch,否则语法错误:    

三.自定义异常的实现:

具体⽅式:
1. ⾃定义异常类,然后继承⾃Exception 或者 RunTimeException
2. 实现⼀个带有String类型参数的构造⽅法,参数含义:出现异常的原因
如下代码:
class UserNameException extends Exception {
    public UserNameException(String message) {
        super(message);
    }
}
class PasswordException extends Exception {
    public PasswordException(String message) {
        super(message);
    }
}

在使用时可以直接调用自定义异常,与官方给定的异常使用方法一样。

  

          

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值