讲个老年人都能听懂的异常处理

Java入门到精通(一)语言基础


为什么要用异常?
原因是在你编写代码的时候编译器会检测出大多数的异常,而一少部分会余留到运行期间解决。当编写大型的程序时,异常可以降低错误处理代码的复杂度。如果不使用异常,那么就必须检查特定的错误,并在程序中的许多地方处理它,从而降低了代码的维护性。如果使用异常,那就不必在方法调用出进行检查,因为异常机制将保证能够捕获这个错误,并且是只有在一个地方即可。

异常的分类

java的异常机制是建立在C++的基础之上。
Thorwable类所有异常和错误的超类,有两个子类Error和Exception,分别表示错误和异常。其中异常类Exception又分为运行时异常(RuntimeException)和非运行时异常,这两种异常有很大的区别,也称之为不检查异常(Unchecked Exception)检查异常(Checked Exception)

运行时异常 —> UncheckedException 程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。编译是可以通过的

非运行时异常—>CheckedException 类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。

ErrorException
Error是程序无法处理的错误,比如OutOfMemoryError、ThreadDeath等。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止,程序将会终止。

Exception是程序本身可以处理的异常,这种异常分两大类,运行时异常和非运行时异常。程序中应当尽可能去处理这些异常。

在这里插入图片描述

常见的异常

异常类意义
ClassCastException类型转换异常
NullPointerException空指针异常
IndexOutOfBoundsException数组下标异常
ArithmeticException算术异常
NumberFormatException字符串转换为数字异常
IllegalArgumentException非法参数异常
SecurityException安全性异常
public class Demo {
    public static void main(String[] args) {
        int[] arr= new int[5];
        System.out.println(arr[5]);
    }
}

在这里插入图片描述

Throwable异常方法

方法介绍
getMessage()获取有关异常事件信息
toString()获取异常的类型与性质
printStackTrace()获取异常发生时执行堆栈的内容
getCause()返回一个Throwable 对象代表异常原因
getStackTrace()返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底
fillInStackTrace()用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中

捕获处理异常

异常处理有两种解决的方案:一种try……catch(捕获并处理异常)语句,另外一种throw(抛出异常)。

try……catch语句

try {
     
}catch (Exception e){
     
}finally {

 }

try:一般都在try里面编写可能发生异常的代码块。
catch: 在try代码块发生异常时,只有进入catch语句块,异常才可以被处理,catch语句块可以有n个(并且子类必须在父类之前,否则就会发生错误)。
finally这个代码块是异常发生不发生都会执行的代码块,都是最后执行。一般情况下该部分都是释放资源或者关闭对象。finally不执行的情况:在finally里面发生异常。

public class Demo {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4,5};
        try{
            System.out.println("第五个元素"+arr[5]);
        }catch (Exception e){//这块也可以将Exception改为ArrayIndexOutOfException
            System.out.println("下标不能大于4,数组下标异常");
        }
    }
}

在这里插入图片描述
从图中可以看出程序并没有因此中断而是对其异常进行了处理最后执行完成。

在这里插入图片描述
在这里插入图片描述
从上图中可以看出两个catch语句的顺序不一样导致了编译器出现了错误提示。Exception是所有的子异常的父类,如果将Exception放在子类之前那么后面的语句就不会执行,也就没有什么意义了。

throws关键词

throws关键词是在声明方法时候用来指定方法可能抛出的异常。

public class asdsad{
    //主线程
    public synchronized void main() throws Exception {
    }
    //子线程
    public synchronized void child() throws Exception {//这种就是throws在方法总抛出异常
    }
    public static void main(String[] args) throws Exception {
        asdsad asdsad = new asdsad();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println();
                    try {
                        asdsad.child();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        },"子线程").start();
        for (int i = 0; i < 10; i++) {
            System.out.println();
            asdsad.main();//这块也可以加try……catch语句  main() 后面就可以不需要了
        }
    }
}

如果方法抛出了异常(child、main),那么在调用的时候就要使用try……catch语句捕获并处理异常或者向上继续抛出异常就像如上代码调用main方法 把异常抛给了Exception处理。

这里需要注意:使用throws为方法抛出异常,如果子类继承父类,子类重写的方法和原父类方法抛出的异常相同、或者是其异常的子类,除非throws异常时RuntimeException。

throw关键词

throw关键词通常用于在方法体之中“制造一个异常”,程序在执行到throw语句时立即终止,它后面的语句都不会得到执行。

public class Demo {
    public static void main(String[] args) {
        int num_1 = 10;
        int num_2 = 0;
        if(num_2 == 0){
            throw new ArithmeticException("除数不为0");
        }
        int res = num_1/num_2;
        System.out.println(res);
    }
}

在这里插入图片描述
throw通常用来抛出用户自定义异常,通过throw关键词抛出异常后,如果想在上一级代码中捕获并处理异常,最好在抛出异常的方法声明中使用throws关键词指明要抛出的异常;如果要捕捉throw抛出的异常,则使用try……catch代码块。

throw与throws区别

  1. throws用在方法声明后面,表示抛出异常,由方法的调用者处理,而throw用在方法体内,用来创造一个异常,由方法体内的语句处理。
  2. throws是声明这个方法会抛出这种类型的异常,以便使他的调用者知道要捕获这个异常,而throw是直接抛出一个异常实列。
  3. throws表示出现异常的一种可能性,并一定会发生这些异常,如果使用throw,就一定产生某种异常。

用户自定义异常

为什么要自定义异常?
就是java内置异常无法识别的情况下才自定义异常、比如:年龄不能为负数。
自定义异常使用场景:
程序中出现错误是符合java语法,编译器检测不出,也可以编译,比如:人的年龄不能为负数,人数不能为小数等等。(这块我总结的不全面)

int age = -10;
System.out.println("小明今年"+age);

如上就可以输出,要避免这种情况我们就可以自定义一个异常类。

public class ageDemo {
    public static void ages(int age) throws MyException{
        if(age<0){
            throw new MyException("年龄不可以使用负数");
        }else{
            System.out.println("小明今年"+age);
        }
    }

    public static void main(String[] args) {
        int age = -10;
        try {
            ages(age);
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
这种情况下可以识别年龄不能为负数。

异常使用的原则(书上内容)

java异常强制用户去考虑程序的强健性和安全性。
应该遵循以下原则:

  1. 不要过度使用异常。虽然通过异常可以增强程序的健壮性,但是如果使用过多的异常处理,可能会影响程序的执行效率。
  2. 不要使用庞大的try……catch块。在一个try块防止大量的代码,业务过于复杂,如果try块出现异常,那么分析找原因的难度将大大增大。
  3. 避免使用catch(Exception e)。因为所有的异常都采用了同一种处理的方式,将导致不能对不同异常分情况处理。比如:ArrayIndexOutOfException和ClassCastException一起都在一个catch代码块处理。
  4. 不要忽略捕捉到的异常,遇到异常一定要及时的处理。
  5. 如果父类抛出多个异常,则覆盖方法必须抛出相同的异常或异常子类,不能抛出新的异常。

不全的内容请大佬补充
看完感觉有用的点个赞,没有的也点个赞
嘻嘻~

  • 11
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值