• 编译时程序透彻理解异常并合理使用异常


    废话就不多说了,开始。。。

        对于异常(Exception)的基本应用相信大家已比拟了解了。不了解的童鞋请参见博文:

        Java异常处置机制

        其实比拟棘手的问题是什么场合用什么异常?checked异常还是runtime异常?是抛出异常还是捕获异常?

        上面举例来探讨一下这个问题;

        

        回顾异常处置机制:

        

        异常机制使程序中异常处置代码和正常业务代码分离,也就是把某些异常交给异常处置器去处置,不让JVM直接处置。

        JMV的处置方式时打印异常跟踪栈的信息,并终止程序运行,比如:

    public static void main(String[] args) {
    	System.out.println(1 / 0);	// 程序抛出java.lang.ArithmeticException: / by zero 然后程序结束。
    	... // 上面的代码没法失失落执行。
    }

        于是乎,我来捕捉一下这个异常好了:

    public static void main(String[] args) {
    	try {
    		System.out.println(1 / 0); // 如果捕捉到异常,生成对应的异常类的对象
    	}catch(ArithmeticException ae) { // 如果捕捉到异常对象,停止自定义异常处置
    		ae.printStackTrace(); // 简略的异常处置,打印异常的跟踪栈信息
    	}
    	System.out.println("main方法结束"); // 这就是异常处置代码和正常业务代码分离的利益,逻辑上清晰,并且独自处置被捕获的异常。
    }

        问,上面的异常须要被捕捉吗?算术异常.

        如果按照平凡思维来思考,程序运行时有异常退出就好了。还捕捉啥呢?还干吗分为checked异常跟runtime异常呢?

        1:捕捉异常是为了让程序独自处置被捕获的异常。

        2:辨别checked异常跟runtime异常,是为了增强程序健壮性。

        checked(知道编译时可能会有问题,我能处置,或者你来处置,最后必须处置(抛向JVM)),编译时就必须给我说清楚怎么处置。

        runtime(知道运行时可能会有问题,我违心处置就处置,你爱处置不处置),运行期出了错你负责。

        无论是哪类异常,都不一定100%发生异常,100%发生异常的代码?你会写吗?你会写编译器让你写吗?

        

        分析与解读:

        

        运行时异常意思就是:编译时没法发现只有在运行时才会出现的异常,比如NullPointerException,编译期是没法判断的。

        如果发生了问题一定是代码bug所致,至于会不会发生问题,要看什么时候程序会运行到出错的地方。

        对于运行时异常,如果知道可能会有问题,又不影响编译,那就向上抛出就好了。声明让调用者处置该运行时异常(站在设计者的角度)。

        运行时异常即使应用try...catch块停止捕捉,那也不是真正能处置失落的,下次程序执行到这又会出现异常,因为代码本身有Bug.

        如果不用异常类去描述这些异常,那程序出现异常了,岂不死翘翘了,所以说,异常的出现是为了增强程序健壮性。

        其它的runtime异常类像:IndexOuterOfBoundsException、ArithmeticException、ClassCastException

        checked异常意思就是:编译时就知道这个地方可能会出现异常,你的程序代码很安康,但是编译器知道你的代码中某个操作会出现问题,或者说你的代码中的某个操作已抛出异常了,你必须对其停止处置。

        每日一道理
    爱,有的时候不须要山盟海誓的承诺,但她一定须要细致入微的关怀与问候;爱,有的时候不须要梁祝化蝶的悲壮,但她一定须要心有灵犀的默契与投合;爱,有的时候不须要雄飞雌从的追随,但她一定须要相濡以沫的支持与懂得。

        比如FileInputStream fis = new FileInputStream("a.txt"); 此构造抛出FileNotFoundException,所以调用者必须处置该异常,否则编译不通过。

        上面的操作是通过打开一个到现实文件的连接来创建一个FileInputStream,文件会100%不存在吗?如果发生错误了肯定是在运行时吧?

        那这老家伙为何抛出编译时异常呢?!他只是觉得你必须对可能产生的异常停止捕捉罢处置了,以为你能搞定的。怎么搞看你需求。

        看一下他的构造器源码:

    public FileInputStream(String name) throws FileNotFoundException { // 他抛出了编译时异常
    	this(name != null ? new File(name) : null);
    }

        再来看一下File构造器的源码:

    public File(String pathname) {
    	if (pathname == null) { // 他抛的是运行时异常!注意是throw,不是throws。
    	    throw new NullPointerException();
    	}
    	this.path = fs.normalize(pathname);
    	this.prefixLength = fs.prefixLength(this.path);
    }

        看出问题了吗?FileInputStream构造器亦可以不处置或者捕获处置该File构造器抛出的运行时异常,但他之所以选择抛出编译时异常,是觉得须要处置并且有能力处置该异常。

        再来看InputStream类的public abstract int read() throws IOException;  read方法涉及到I/O操作,须要访问外部资源。由于外部资源不受JVM控制,

        所以有可能会出现异常,操作失败或者操作中断或者没有权限访问。对于这些可能出现的异常,不也是运行时才能出现的吗?抛出IOException,还是觉得须要处置罢了。增强程序健壮性。

        有人说他内部也没有再去调用抛出运行时异常的方法了啊?这里read方法做的是访问系统底层操作,代码不是Java写滴。

        

        透彻懂得编译时异常(checked):

        

        到底编译时异常是个啥玩意?我都没有运行程序咋还就出现异常了?别叫名字给骗了,编译时异常那就是编译错误。

        编译时异常是对运行时异常的约束。约束你对异常停止处置。真正的异常是运行时异常。编译时异常检查的还是语法错误,因为你应用关键字抛出了编译时异常类。

        

        总结:

        

        处置异常,是一门学问,异常处置的顺遂不顺遂与后期对项目的面向对象分析(OOA)是否清晰合理有直接关系。

        在这里只是对异常停止了看似易懂的描述,真正到了现实开发中,因为项目复杂度的晋升,对异常的合理处置也必须得要求很灵活。

        而这个灵活须要靠开发教训的增多而产生一种感到,感到是建立在正确的认识以后的,感到就没法像大家描述了,感到是没法用语言表达的,哈哈。

        原创文章,转载请注明出处:

        http://blog.csdn.net/thinking_in_android

    文章结束给大家分享下程序员的一些笑话语录: N多年前,JohnHein博士的一项研究表明:Mac用户平均IQ要比PC用户低15%。超过6000多的参加者接受了测试,结果清晰的显示IQ比较低的人会倾向于使用Mac。Mac用户只答对了基础问题的75%,而PC用户却高达83%。

  • 相关阅读:
    guzzle下载图片(laravel+vue)
    leetcode——131.分割回文串
    leetcode——139.单词拆分
    leetcode——115.不同的子序列
    leetcode——72.编辑距离
    leetcode——87.扰乱字符串
    leetcode——123. 买卖股票的最佳时机 III
    leetcode——132. 分割回文串 II
    leetcode——124. 二叉树中的最大路径和
    leetcode——51.N皇后
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3076790.html
Copyright © 2020-2023  润新知