资讯专栏INFORMATION COLUMN

《Java编程思想》 -- 异常总结

Pocher / 1269人阅读

摘要:总结异常总的来说还是很重要的,也是保障程序健壮性很重要的一栏,并且可以达到立竿见影的效果,这里只是基本总结了异常的一些常见问题,很多还得在自己运用的过程中去探索。

概述

说起异常,我就想起了Bug,也就是常说的信春哥,无Bug,什么是Bug呢?我理解的Bug就是没有按照自己原先假想的逻辑去执行,这其中包括了两个方面,一方面是代码语法问题,一方面是逻辑问题,就比如正常逻辑买了东西要付款,但是买家买了东西却没有付款,直接拿东西走了,这是逻辑问题,或者是本来数组存储3个元素,你却存了4个,这时候也出现了Bug,程序报错了,这种Bug就是异常。
异常也是Java类的一种,用new创建对象,他们的结构是这样的:

Throwable

error

Exception

恩,就是这样,异常分为错误和异常,感觉有点绕口,但就是这样,像error这种错误是在编译期间就会报出来的,如果你使用的是IDE,所以我们只需要关注Exception异常就可以了。

获取异常和处理异常

获取和处理异常可能就是异常的全部,我们的一个原则就是:

发生异常就得让程序员知道

获取异常

怎么获取异常呢?Java给出了try关键字用来解决,我们只需要将可能出现异常的代码放在try中就可以了,就像这样:

    try{
        ...
    }

java给出了尽量优雅的解决方案来处理异常,它不希望处理异常的代码和本身的业务代码有过多的混合,获取到异常就该处理异常,这时候就应该这样写了:

    try{
        ...
    }catch(Type1 type1){
        ...
    }catch(Type2 type2){
        ...
    }

catch中的type代表了在try中可能出现的异常类型

catch如何匹配异常?

按顺序从第一个到最后一个,如果发现异常匹配,就停止匹配,和switch模式不一样

基类包含子类异常,如果第一个是Exception,那么后面的都不用匹配了

那么catch中怎么处理这个异常呢?

不作处理(会出现“吞食”)

打印到控制台

写入日志

继续向上抛

在try块中抛出异常,我们在catch中会匹配到相应的异常类型,这时候我们就会拿到对应的异常对象的引用,我们调用throwalbe的方法用于处理:

public class ExceptionMethods {
    public static void main(String[] args) {
        try {
            throw new Exception("My Exception");
        } catch (Exception e) {
            System.out.println("Caught Exception");
            System.out.println(e.getMessage());
            System.out.println(e.getLocalizedMessage());
            System.out.println(e);
            System.out.println(e.toString());
            e.printStackTrace();
            e.printStackTrace(System.out);
        }
    }
}

我们一般使用e.printStackTrace();打出异常栈信息即可

或者是写入Log,使用logger.error

每个人处理处理异常的方式可能不尽相同

我们除了可以使用try来捕获异常,我们也可以将这个异常抛出去,我们可以把异常比作现在这种制度,地球村出了点问题,村长衡量了一下,觉得这事情自己处理不了,就交给乡长了,这种把问题交给上层或者是Java编程思想中说的跳出当前环境,交给一个更大的环境去处理,这也是Java异常处理的一种思路。

if(t == null)
    throw new NullPointerException();

其实异常最重要的就是异常的名称,现在Java正在扩充异常的种类,但是很多异常可能不是我们想要的,那么我们就可以自定义异常:

class SystemErrException extends Exception{

}

这就是一个异常类,我们继承了Exception,这个SysteErrException就可以用于我们处理异常的时候了,当然我们可以给他加点参数:

class SystemErrException extends Exception{
    public SystemErrException(){ 
    }
    public SystemErrException (String message){
        super(message);
    }
} 

或者是这样:

class SystemErrException extends Exception{
    private int i;
    public SystemErrException(){ 
    }
    public SystemErrException (String message){
        super(message);
    }
    public SystemErrException (String message, int i){
        super(message);
        this.i = i;
    }
} 

这只不过是多加了几个参数,但是这些一般是没什么必要的。

throws

说到这,就得说另一个关键字throws,看清楚,不是throw,而是throws,这可能也是面试新手的时候会问的一个问题,throws是异常中的一个申明,在IO学习中会非常常见,它是一个声明,编译器检查到说你这段代码可能会发生什么异常,你要声明一下,这时候你就要在方法上声明:

public void inputFile() throws IOException{
    ....
}
finally

finally用处就和他的意思相符,表示最终的含义,也就是finally里面的代码一定会得到执行:
案例一

public class FinallyException {
    static int count = 0;

    public static void main(String[] args) {
        while (true){
            try {
                if (count++ == 0){
                    throw new ThreeException();
                }
                System.out.println("no Exception");
            }catch (ThreeException e){
                System.out.println("ThreeException");
            }finally {
                System.out.println("in finally cause");
                if(count == 2)
                    break;
            }
        }
    }
}

class ThreeException extends Exception{

}

执行结果:

ThreeException
in finally cause
no Exception
in finally cause

案例二:return案例

public class MultipleReturns {

    public static void f(int i){
        System.out.println("start.......");
        try {
            System.out.println("1");
            if(i == 1)
                return;
            System.out.println("2");
            if (i == 2)
                return;
            System.out.println("3");
            if(i == 3)
                return;
            System.out.println("else");
            return;
        }finally {
            System.out.println("end");
        }
    }

    public static void main(String[] args) {
        for (int i = 1; i<4; i++){
            f(i);
        }
    }
}

执行结果:

start.......
1
end
start.......
1
2
end
start.......
1
2
3
end
最佳实践

我们可能遇到这种情况,打开一个文件,读取文件,关闭文件,正常逻辑是这样的,但是这样会有几个问题:

在打开文件的过程中出现异常,但是还要关闭文件

就像这样:

    try{
        A a = new A();
        ...
    }catch(){
        ...
    }finally{
        a.close();
    }

A在创建过程中会出现异常,但是还是会执行a的方法,比如关闭文件

所以我们应该这么做:

    try{
        A a = new A();
        try{
            ...
        }finally{
            a.close();
        }
    }catch(){
        ...
    }
异常栈

一般报错都会报一大堆错误,大家无从看起,其实异常报错也是有规律的,这就是栈结构,先进后出,举个栗子:

public class WhoCalled {
    static void f() {
        try {
            throw new Exception();
        } catch (Exception e) {
            for (StackTraceElement ste : e.getStackTrace()){
                System.out.println(ste.getMethodName());
            }
        }
    }

    static void g(){
        f();
    }

    static void h(){
        g();
    }


    public static void main(String[] args) {
        f();
        System.out.println("---------------------------");
        g();
        System.out.println("---------------------------");
        h();
        System.out.println("---------------------------");

    }
}

运行结果:

f
main
---------------------------
f
g
main
---------------------------
f
g
h
main
---------------------------

可以看到异常信息都是从内到外的,按我的理解查看异常的时候要从第一条异常信息看起,因为那是异常发生的源头。

总结

异常总的来说还是很重要的,也是保障程序健壮性很重要的一栏,并且可以达到立竿见影的效果,这里只是基本总结了异常的一些常见问题,很多还得在自己运用的过程中去探索。

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

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

相关文章

  • Java编程思想》读后总结(一)

    摘要:前言编程思想这本书,陆陆续续读了年,终于基本都浏览了一遍。每个对象对外暴露接口,程序通过对象暴露的接口向对象发送消息,获取该对象的服务能力。异常处理异常处理,为编写程序阶段提供了一种预见性的防止程序崩溃的出路。 前言 《Java编程思想》这本书,陆陆续续读了1年,终于基本都浏览了一遍。通过这本书,试图理解作者的想法,才真的体会到Java思想。感谢本书的作者,不仅讲述了java的语法,更...

    hufeng 评论0 收藏0
  • Java编程思想学习录(连载之:异常

    摘要:系列博文目录编程思想学习录连载之一切都是对象编程思想学习录连载之初始化与清理编程思想学习录连载之内部类编程思想学习录连载之异常本篇文章将讲述关于异常的相关知识注本文首发于公众号,可长按或扫描下面的小心心来订阅基本概念使用异常来提供一致性的错 showImg(https://segmentfault.com/img/remote/1460000013228854); Thinking ...

    pkhope 评论0 收藏0
  • Java编程思想》读书笔记-类与对象

    摘要:类最基本的作用,在于通过类获取到相应的对象,在向对象发送消息时以期望对象做某些特定的事情。先导概念引用中一切皆对象,因此采用一个指向对象的引用来操纵对象。对象可以存活于作用域之外。 欢迎各位读者关注我的微信公众号,共同探讨Java相关技术。生命不止,学习不休! showImg(https://segmentfault.com/img/bVboaBO?w=129&h=129); 也许你慢...

    NickZhou 评论0 收藏0
  • Java 学习路线之四个阶段

    摘要:写这篇总结,主要是记录下自己的学习经历,算是自己对知识的一个回顾。这个阶段学习的时候,要学会使用开发工具,比如或者来学习。这个阶段需要自己对自己有很强的自律去学习,不要看了一半就放弃了。 showImg(https://segmentfault.com/img/bVbaNtw?w=1232&h=822); 写这篇总结,主要是记录下自己的学习经历,算是自己对知识的一个回顾。也给想要学习 ...

    fredshare 评论0 收藏0
  • Java 学习路线之四个阶段

    摘要:写这篇总结,主要是记录下自己的学习经历,算是自己对知识的一个回顾。这个阶段学习的时候,要学会使用开发工具,比如或者来学习。这个阶段需要自己对自己有很强的自律去学习,不要看了一半就放弃了。 showImg(https://segmentfault.com/img/bVbaNtw?w=1232&h=822); 写这篇总结,主要是记录下自己的学习经历,算是自己对知识的一个回顾。也给想要学习 ...

    CNZPH 评论0 收藏0

发表评论

0条评论

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