死磕Java之Java异常机制

摘要

程序可以使用异常来指定发生的错误。抛出异常,使用throw语句并为其提供一个异常对象,以提供有关所发生的特定错误信息。抛出未捕获的已检查出的异常的方法必须再其声明包含一个抛出子句。

一、什么是Exception?

看到Exception你一定对这个很熟悉,但是又很陌生,一般是拿来就用的,遇到异常就抛出来抛出去的。但是当别人问你:什么是Exception?你支支吾吾的说不出来,又说不出来个1还是2,被我说准了吧。如果被我说准了,那就继续往下看,这篇文章很符合你,我女朋友能看懂。相信你也能看懂。如果你很了解,那么就不要继续看了。

说到这可能还有对Exception没印象的,请看:try {...}catch (Exception e){...}现在是不是知道是啥了,如果你看到了这里,那么请继续往下看。

什么是Exception?
很多博客都是直接给出代码,但是我还是先给出定义,想学好,就必须知道它为什么要出现。

定义:Exception是一个处理异常的机制,在程序的执行期间,突然出现了问题,那么异常处理机制就会派上用场了。

trycatchfinally说明:
trytry块标识可能发生异常的代码块;
catchcatch块标识一个称为异常处理程序的代码块,它开业i处理特定类型的异常;
finallyfinally块标识一个不管怎样都会执行的代码块,经常用在关闭文件、恢复资源以及在try块中包含的代码之后进行清理的位置。

try语句应该至少包含一个catch块或finally块,并且可以有多个catch块。

try {
	//可能发生运行错误的代码;
}catch (异常类型1  异常类型对象的引用){
	//处理异常类型1的代码
}catch (异常类型2  异常类型对象的引用){
	//处理异常类型2的代码
}finally {
	//用于最后处理的代码,此处的代码,不管怎么样都会执行。
}

二、Java异常的分类(你是不是只知道2种,其实有3种)

很多都说有2种异常,其实是有3种(我翻了java的官方的网站)。

3种Java异常情况分别是:检查时异常错误异常运行时异常

第一种:检查时异常
通常是编写好的程序,这些异常能是在人的预期之内的

举个例子:假设有一个程序,是处理文件的。这就要求用户输入这个文件的地址路径,然后将文件地址传给相应的I/O处理,拿FileRedaer来说,如果路径对的话,则程序就会正常运行。但是程序不能保证用户每次都会提供正确无误的路劲,如果文件路径错误的话,则文件就不存在,就会报出FileNotFoundException的异常。此时程序就可以提示用户必须输入正确的路径。

例如:用户输入账号密码,密码错误,就可以提示用户输入错误。

第二种:错误异常
通常这类异常是由程序外部的特殊条件造成的,应用程序通常是无法预期的
例如:还拿用户操作文件来说吧,程序需要用户提供一个文件的地址。如果地址正确了,但是由于机器的故障而导致的错误,打不开等因素。就叫做错误异常。

错误异常是无法捕获的。错误是由Error及其子类指示的那些异常

第三种:运行时异常
这类异常时是发生在程序内部的,通常是由编程错误造成的
例如:逻辑错误或API使用不当。

二、捕获和处理异常

接下来一起分析下trycatchfinally三个异常处理块的使用。

(1)(try-catch)

捕获单个异常

try{
	//会发生异常的代码块
}catch(异常类型  异常变量名){
	//发生异常后,应该怎么做
}

多重捕获块

try{
	//会发生异常的代码块
}catch(异常类型1  异常变量名1){
	//发生异常类型1后,应该怎么做
}catch(异常类型2  异常变量名2){
	//发生异常类型2后,应该怎么做
}catch(异常类型3  异常变量名3){
	//发生异常类型3后,应该怎么做
}

try:用于监听异常(监听何时出现异常)
catch:用于捕获处理异常(发生异常怎么处理)

解释
try后面的一对大括号内的内容就会受到监控,存放一些可能会出现问题的代码,一旦触发了,就说明有异常要发生了。catch代码块是处理这些异常的,一旦出现异常之后,该如何做?那就在这里面进行操作。

例子1:最通用的一个例子,除数

        System.out.println("开始执行");
        int a = 10;
        int b = 0;
        int c = 5;
        System.out.println(a/b);
        System.out.println(a+c);
        System.out.println("我又做其他的事情了");
        System.out.println("执行结束了");

可以看到会报出以下异常:同时也不会往下执行,程序直接停止了。
在这里插入图片描述
捕获异常来救一下

       System.out.println("开始执行");
        int a = 10;
        int b = 0;
        int c = 5;

        try {
            System.out.println(a/b);
        }catch (ArithmeticException A){
            System.out.println("出现异常了,错误消息:"+A.getMessage());
        }
        System.out.println("我又做其他的事情了");
        System.out.println(a+c);
        System.out.println("执行结束了");

在这里插入图片描述
通过上例可以看到,被监控的语句中先依次正常执行,当遇到存在问题的语句时,找到匹配异常,并且执行catch块中的语句而一般来说我们会在catch语句块中通过异常对象执行异常方法。

方法方法 说明
public String getMessage() 回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了
public Throwable getCause() 返回一个Throwable 对象代表异常原因
public String toString() 使用getMessage()的结果返回类的串级名字
public void printStackTrace() 打印toString()结果和栈层次到System.err,即错误输出流

(2)(try-catch-finally)

try-catch的基础上再补充一个finally的知识
finally代码块中的内容不管tay-catch两个代码块的代码如何,finally代码块中的内容,都会执行。

语法如下:

try{
    ......
}catch(异常类型1 异常的变量名1){
    ......
}catch(异常类型2 异常的变量名2){
    ......
}finally{
    ......
}

无论是否发生异常,fianlly始终都是会运行的

注意:当finally遇到return

例如:

public class Demo2 {
    public static void main(String[] args) {
        System.out.println(test());
    }

    public static String test(){
        int[] array = new int[2];
        try{
            array[3] = 0;
            return "This is try";
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println(e);
            return "This is catch 1";
        }catch (Exception e){
            System.out.println(e);
            return "This is catch 2";
        }finally {
            System.out.println("This is finally");
            //return "This is finally's return";
        }
    }
}

//运行结果
java.lang.ArrayIndexOutOfBoundsException: 3
This is finally
This is catch 1

由此我们得出一个结论:在catch中遇到return时,仍然会先执行finally语句

(3)throw/throws

将自己处理不了的,在方法或者语句上声明,告诉调用者,这里有问题。

 public static void main(String[] args) {
        int a = 10;
        int b = 0;
        System.out.println(aAndb(a, b));
    }

    public static int aAndb(int a,int b){
        if(b==0){
            throw new ArithmeticException();
        }else{
            return a/b;
        }
    }

在这里插入图片描述

上层处理异常

  public static void main(String[] args) {
        int a = 10;
        int b = 0;
        try {
            System.out.println(aAndb(a, b));
        }catch (ArithmeticException A){
            System.out.println("出错了,错误消息为:"+A.getMessage());
        }
    }

    public static int aAndb(int a,int b){
        if(b==0){
            throw new ArithmeticException("b不能为0");
        }else{
            return a/b;
        }
    }

在这里插入图片描述

(4)throws和throw的区别

1、throws

  • 用在方法声明后,跟的是异常类名
  • 可以跟多个异常类名,用逗号隔开
  • 表示抛出异常,由该方法的调用者来处理
  • throws表示出现异常的一种可能性,不一定会发生这些异常

2、throw

  • 用在方法体内,跟的是异常对象名
  • 只能抛出一个异常对象名
  • 表示抛出异常,由方法体内的语句处理
  • 执行throw则一定抛出了某种异常

三、自定义一个万能的异常类

Java自带的异常类,基本上可以满足我们遇到的大部分问题,除此之外,还可以自定义异常类。

定义一个通用的异常类

//通用异常类
class ZhenghuiException extends Exception {
    public ZhenghuiException(String msg)
    {
        super(msg);
    }
}

测试代码

public class ListTest {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        try {
            System.out.println(aAndb(a, b));
        }catch (ZhenghuiException A){
            System.out.println("出错了,错误消息为:"+A.getMessage());
        }
    }

    public static int aAndb(int a,int b) throws ZhenghuiException {
        if(b==0){
            throw new ZhenghuiException("b不能为0");
        }else{
            return a/b;
        }
    }

}

在这里插入图片描述

发布了154 篇原创文章 · 获赞 617 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_17623363/article/details/104908020