资讯专栏INFORMATION COLUMN

【JAVA系列】关于异常的一些事

不知名网友 / 1443人阅读

摘要:程序块若有异常发生,程序的运行便重点,并抛出异常类所产生的对象。关键字我们可以使用关键字把可能抛出的异常显式的标注在方法定义的位置从而提醒调用者要注意捕获这些异常。


前言

JAVA提供强大的异常处理机制,在Java中,所有的异常都会被封装到一个类中,程序出错时会将异常抛出。


一、如何知道程序错误

代码中的错误是客观存在的,没有十全十美的代码,代码多到一定程序,我们就需要不断维护、检查代码的错误,确保健壮性。

在Java中,我们有以下两种方式告诉程序代码发生错误:

  1. LBYL: Look Before You Leap. 在操作之前就做充分的检查
  2. EAFP: It’s Easier to Ask Forgiveness than Permission. “事后获取原谅比事前获取许可更容易”. 也就是先操作, 遇到问题再处理.

简单来说就是第一种没有使用异常,第二采用了异常的方法

代码风格如下:

LBYL: Look Before You Leap. 在操作之前就做充分的检查:

boolean ret = false;ret = 登陆游戏();if (!ret) { 处理登陆游戏错误;    return; }ret = 开始匹配();if (!ret) { 处理匹配错误;    return; }ret = 游戏确认();if (!ret) { 处理游戏确认错误;    return; }ret = 选择英雄();if (!ret) {    处理选择英雄错误;    return; }ret = 载入游戏画面();if (!ret) { 处理载入游戏错误;    return; }......

It’s Easier to Ask Forgiveness than Permission. “事后获取原谅比事前获取许可更容易”. 也就是先操作, 遇到问题再处理:

try {    登陆游戏();    开始匹配();    游戏确认();    选择英雄();    载入游戏画面();   ...} catch (登陆游戏异常) {    处理登陆游戏异常;} catch (开始匹配异常) { 处理开始匹配异常;} catch (游戏确认异常) { 处理游戏确认异常;} catch (选择英雄异常) { 处理选择英雄异常;} catch (载入游戏画面异常) { 处理载入游戏画面异常; }.....

对比两种不同风格的代码, 我们可以发现:

使用第一种方式, 正常流程和错误处理流程代码混在一起, 代码整体显的比较混乱.

而第二种方式正常流程和错误流程是分离开的, 更容易理解代码

二、常见的异常

所谓异常指的就是程序在 运行时出现错误时通知调用者的一种机制

异常的种类有很多, 不同种类的异常具有不同的含义, 也有不同的处理方式,下面介绍几种常见异常:

1.算术异常

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

2.数组越界异常

public static void main(String[] args) {        int []arr=new int[4];        System.out.println(arr[10]);    }

3.空指针异常

public static void main(String[] args) {        String str=null;        System.out.println(str.length());    }

二、异常的基本用法

1.如何捕获异常

异常处理是由try、catch与finally等3个关键字组成的程序块。
其异常的基本语法:

try{		要检查的程序语句;		...		}catch(异常类 对象名称){		异常发生时的处理语句;		}[catch(异常类 对象名称){		异常发生时的处理语句;		}catch(异常类 对象名称){		异常发生时的处理语句;		}		...][finally{		一定会运行到的程序代码;		}]			

异常的处理流程如下:

  1. 首先,我们把所有可能发生异常的语句都放到一个try之后由{}所形成的区块,这个区块称为“try区块”。程序通过try{}区块准备捕捉异常。try程序块若有异常发生,程序的运行便重点,并抛出“异常类所产生的对象”。
  2. 抛出的对象如果属于catch()括号内欲捕获的异常类,catch则会捕捉此异常,然后进入catch的块里继续运行。
  3. 无论try程序块是否捕捉到异常,或者捕捉到的异常是否与catch()括号内的异常相同,最终一定会运行finally块里的程序代码。

【注意】
finally块时可以省略的,如果省略了finally块,那么在catch()块运行结束后,程序将跳到try-catch块之后继续执行。

流程图如下:
下面看一个例子:
不进行异常处理:

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


使用异常处理就能正常编译:

 public static void main(String[] args) {        int[] arr = {1, 2, 3};        try{            System.out.println(arr[10]);        }catch (ArrayIndexOutOfBoundsException e){            System.out.println("我在这里捕捉到一个异常");        }        System.out.println("hello!!!");    }


如果我想要知道详细的异常信息的话,则需要使用异常对象的printStackTrace()方法:


【异常处理机制小结】
当异常发生时,通常用两种方法处理:

  1. 一种时交由Java默认的异常处理机制做处理。但这种处理方式,Java通常只能输出异常信息,接着便终止程序的运行
  2. 一种时用自行编写的try-catch-finally块来捕捉异常,这样的好处是可以灵活操控程序的流程,做出最适当的处理。

2.异常类的处理流程

习惯上将Error类与Exception类统称为异常类,但二者本质上是不同点。
Error类通常指的是Java虚拟机出错,用户无法在程序里处理这种错误。
Exception类包含了一般性的异常,这些异常在捕捉到之后便可做妥善的处理,以确保程序继续运行。

下面是异常处理的流程:

  1. 如果程序发生异常,那么会自动地由JVM根据异常的类型,实例化一个指定异常类的对象,如果这个时候程序之中没有任何的异常操作,则这个异常类的实例化对象将交给JVM进行处理——进行异常信息的输出,而后中断程序执行
  2. 如果程序之中存在异常处理,则会由try语句捕获产生的异常类对象;然后将该对象与try之后的catch进行匹配,如果匹配成功,则使用指定的catch进行处理,如果没有匹配成功,则向后面的catch继续匹配,如果没有任何的catch匹配成功,则这个时候将交给JVM执行默认处理。
  3. 不管是否有异常都会执行finally程序,如果此时没有异常,执行完finally,则会继续执行程序之中的其他代码,如果此时有异常没有能够处理(没有一个catch可以满足),那么也会执行finally,但执行完finally之后,将默认交给JVM进行异常信息的输出,并且程序中断。

3.throws关键字

我们可以使用 throws 关键字, 把可能抛出的异常显式的标注在方法定义的位置. 从而提醒调用者要注意捕获这些异常。
格式如下:

访问权限 返回值类型 方法名称(参数列表)throws 异常类{	//方法体;}

上面格式包括两个部分:一个普通方法的定义,与方法定义模式无区别。方法后面紧跟”throws异常类“,它位于方法体{ }之前,用来检测当前方法是否有异常,若有,则将该异常提交给直接使用这个方法的方法。

 //定义私有化静态方法,并使用throws抛出异常    //一旦方法出现异常,setZero()方法自己并不处理,而是将异常提交给它的上级调用这main()方法    private static void setZero(int[] arr,int index)throws ArrayIndexOutOfBoundsException{        arr[index]=0;    }    public static void main(String[] args) {        int []arr=new int[5];        try{            setZero(arr,10);        }catch (ArrayIndexOutOfBoundsException e){            System.out.println("数组超出绑定方位!");            System.out.println("异常:"+e);        }        System.out.println("main()方法结束!");    }

4.throw关键字

上面的所有异常类对象全部都是由JVM自动实例化的,但优势我们也想能进行异常类对象的实例化操作,手工抛出异常,则此时需要throw关键字。

public static void main(String[] args) {        try {            //抛出异常的实例化对象            throw  new ArrayIndexOutOfBoundsException("/n我是手工异常:/n数组下标越界");        }catch (ArrayIndexOutOfBoundsException e){            System.out.println(e);        }    }

三、自定义异常类

为了处理各种异常,Java可通过继承的方式运行用户编写自己的异常类,因为所有可处理的异常均继承自Exception类,因此自定义异常类也不例外。

语法如下:

class 异常名称 extends Exception{...}

我们可以在自定义异常类里编写方法处理相关时间,甚至不编写任何语句也可以正常工作,因为父类Exception已提供相当丰富的方法,通过几次子类均可以使用它们。

static class MyException extends Exception{        public MyException(String msg){            super(msg);//调用Exception类的构造方法,存入异常信息        }    }    public static void main(String[] args) {        try{            throw new MyException("自定义异常");        } catch (MyException e) {            e.printStackTrace();            System.out.println(e);        }    }


最后

前路漫漫啊,前路漫漫啊…

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/125643.html

相关文章

  • 【面试】Java基础中那些-One

    摘要:前言面试中对于技术职位,一般分笔试与面谈,如果面试官的一些小问题你可以立马找到对应的知识点扩展开来,那么这就是你的优势,本系列将讲述一些面试中的事,不会很详细,但是应该比较全面吧。 前言 面试中对于技术职位,一般分笔试与面谈,如果面试官的一些小问题你可以立马找到对应的知识点扩展开来,那么这就是你的优势,本系列将讲述一些java面试中的事,不会很详细,但是应该比较全面吧。 主要内容 说到...

    Stardustsky 评论0 收藏0
  • Java 最困扰你那些

    摘要:没有操作符重载。最终类型在所有情况下应该是默认的,并用作为修饰符。这样就会减少现在你会在和一些第三方的中见到的那些令人困惑的历史遗留方法。在用过或是最新的之后你会觉得非常的繁琐。这是最常见的关于的吐槽,但它这就是事实。 啊哈Reddit,没了你我们还能在哪里从鱼目混珠的网络中提炼真正的精华?就在这杂乱无章的论坛中,的的确确存在着这样一些精辟的讨论。 比如有个叫Shambloroni的...

    Lorry_Lu 评论0 收藏0
  • 后端知识拓展 - 收藏集 - 掘金

    摘要:阻塞,非阻塞首先,阻塞这个词来自操作系统的线程进程的状态模型网络爬虫基本原理一后端掘金网络爬虫是捜索引擎抓取系统的重要组成部分。每门主要编程语言现未来已到后端掘金使用和在相同环境各加载多张小图片,性能相差一倍。 2016 年度小结(服务器端方向)| 掘金技术征文 - 后端 - 掘金今年年初我花了三个月的业余时间用 Laravel 开发了一个项目,在此之前,除了去年换工作准备面试时,我并...

    CoderBear 评论0 收藏0
  • 后端知识拓展 - 收藏集 - 掘金

    摘要:阻塞,非阻塞首先,阻塞这个词来自操作系统的线程进程的状态模型网络爬虫基本原理一后端掘金网络爬虫是捜索引擎抓取系统的重要组成部分。每门主要编程语言现未来已到后端掘金使用和在相同环境各加载多张小图片,性能相差一倍。 2016 年度小结(服务器端方向)| 掘金技术征文 - 后端 - 掘金今年年初我花了三个月的业余时间用 Laravel 开发了一个项目,在此之前,除了去年换工作准备面试时,我并...

    Carl 评论0 收藏0
  • Thread类源码解读(3)——线程中断interrupt

    摘要:现在终止一个线程,基本上只能靠曲线救国式的中断来实现。中断机制的核心在于中断状态和异常中断状态设置一个中断状态清除一个中断状态方法同时会返回线程原来的中断的状态。中断异常中断异常一般是线程被中断后,在一些类型的方法如中抛出。 前言 系列文章目录 线程中断是一个很重要的概念,通常,取消一个任务的执行,最好的,同时也是最合理的方法,就是通过中断。 本篇我们主要还是通过源码分析来看看中断的概...

    fevin 评论0 收藏0

发表评论

0条评论

不知名网友

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<