优雅编程之这样处理异常,你就“正常”了(七)

开心一笑

【一交警在开罚单,一男子叼着烟过来喊:你除了开罚单还会干什么?
交警没理睬,男子继续:有种拖走啊!
交警很愤怒,男子继续:有种拖走啊!
交警忍无可忍拿出对讲机,拖车时交 警和蔼说:下午到五大队来处理!
男子:关我鸟事!车又不是我的!
说完哼着小曲骑着电瓶车走了】

提出问题

如何处理异常才能使代码更简洁???

解决问题

程序中进程会出现异常,如何优雅处理它,需要一定技巧,以下是来自《代码整洁之道》的几点总结:

1)使用异常而非返回码,这里的异常处理就是我们经常写的try catch;

package com.hwy.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CodeCleanTest {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    public boolean eat(){

        boolean isCompleted = false;

        try{
            System.out.println("美味");
            isCompleted = true;
        }catch (Exception e){
            log.info(e.getMessage());
        }

        return isCompleted;
    }

}

2)不要返回null值:这样的话调用者就要处理null,增加工作量;解决:抛出异常或者返回特例对象(利用Collections.emptyList());

错误示例:

package com.hwy.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;

public class CodeCleanTest {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    /**
     * 约会
     */
    public void datWithGirl(){
        List<String> snacksList =  buySnacks();
        if(null != snacksList){
            List<String> litter =  eatSnacks(snacksList);
            dropLitter(litter);
        }
    }

    /**
     * 买零食(事实这些注释都是不需要,只是为了大家理解)
     * @return
     */
    public List<String> buySnacks(){

        List<String> snacksList = new ArrayList<>();
        snacksList.add("牛奶");
        snacksList.add("巧克力");
        snacksList.add("土豆片");
        return snacksList;
    }

    /**
     * 吃零食(事实这些注释都是不需要,只是为了大家理解)
     * @param snacks
     */
    public List<String> eatSnacks(List<String> snacks){
        if(null != snacks) {
            for (String snack : snacks) {
                System.out.println("一起吃" + snack);
            }
        }
        return snacks;
    }

    /**
     * 仍垃圾(事实这些注释都是不需要,只是为了大家理解)
     * @param litter
     */
    public void dropLitter(List<String> litter){

        if(null != litter){
            for(String snack:litter){
                System.out.println("一起吃" + snack);
            }
        }
    }
}

正确示例:可看里面详细的注释,要有耐心哦!

package com.hwy.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;

public class CodeCleanTest {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    /**
     * 约会
     */
    public void datWithGirl() throws Exception {
        List<String> snacksList =  buySnacks();
        /** 利用逆向思维,抛出一个业务异常,这里我只是用简单的exception代替 **/
        if(null == snacksList || snacksList.size() ==0){
            throw new Exception("你没买到零食或买到的零食有问题,请检查!");
        }
        /** 代码执行到这一步就说明snacksList不为null,之后的所有
         * 操作都不用判断snacksList是否为空 **/
        List<String> litter =  eatSnacks(snacksList);
        dropLitter(litter);
    }

    /**
     * 买零食(事实这些注释都是不需要,只是为了大家理解)
     * @return
     */
    public List<String> buySnacks(){

        List<String> snacksList = new ArrayList<>();
        snacksList.add("牛奶");
        snacksList.add("巧克力");
        snacksList.add("土豆片");

        /** 在这里如果snacksList为空的话,可以用Collections.emptyList(),就不用
        ** 在上面处理异常了 **/
        //return Collections.emptyList();
        return snacksList;
    }

    /**
     * 吃零食(事实这些注释都是不需要,只是为了大家理解)
     * @param snacks
     */
    public List<String> eatSnacks(List<String> snacks){
        for (String snack : snacks) {
            System.out.println("一起吃" + snack);
        }
        return snacks;
    }

    /**
     * 仍垃圾(事实这些注释都是不需要,只是为了大家理解)
     * @param litter
     */
    public void dropLitter(List<String> litter){

        for(String snack:litter){
            System.out.println("扔掉垃圾:" + snack);
        }
    }
}

3)在方法中返回null值是很糟糕的,但讲null传递给其他方法就更糟糕了,具体解决方法如下:

package com.hwy.test;

import org.junit.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;

public class CodeCleanTest {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    public static void main(String[] args) throws Exception {
        datWithGirl();
    }

    /**
     * 约会
     */
    public static void datWithGirl(){
        /** 这里返回为null **/
        List<String> snacksList =  buySnacks();
        /** 在吃零食方法中,需要处理异常 **/
        List<String> litter =  eatSnacks(snacksList);
        dropLitter(litter);
    }

    /**
     * 买零食(事实这些注释都是不需要,只是为了大家理解)
     * @return
     */
    public static List<String> buySnacks(){
        return null;
    }

    /**
     * 吃零食(事实这些注释都是不需要,只是为了大家理解)
     * @param snacks
     */
    public static List<String> eatSnacks(List<String> snacks){


        /** 第一种处理方法 **/
//        if(null == snacks){
//            throw new NullPointerException("没有零食吃!!!");
//        }

        /** 第二种处理方法, **/
        Assert.assertNotNull("没有零食吃!!!",snacks);
        for (String snack : snacks) {
            System.out.println("一起吃" + snack);
        }
        return snacks;
    }

    /**
     * 仍垃圾(事实这些注释都是不需要,只是为了大家理解)
     * @param litter
     */
    public static void dropLitter(List<String> litter){
        for(String snack:litter){
            System.out.println("一起吃" + snack);
        }
    }
}

运行结果:

java.lang.AssertionError: 没有零食吃!!!
at org.junit.Assert.fail(Assert.java:93)
at org.junit.Assert.assertTrue(Assert.java:43)
at org.junit.Assert.assertNotNull(Assert.java:526)
at com.hwy.test.CodeCleanTest.eatSnacks(CodeCleanTest.java:48)
at com.hwy.test.CodeCleanTest.datWithGirl(CodeCleanTest.java:23)
at com.hwy.test.CodeCleanTest.main(CodeCleanTest.java:13)

4)不管做哪种类型的应用,都应该尽可能向用户隐藏异常的发生,除非发生了不可挽救的状况,这才是符合最小惊讶原则的设计

5)异常的信息应该足够充分(包含出错的位置以及原因)

6)避免使用可控异常(checked exception):因为处理它们需要修改函数头(在每个调用该函数的函数添加throw Exception),违反了开放-闭合原则;应该使用不可控异常(runtime exception);

感悟.png

读书感悟

来自《峰与谷》

  • 在我们的工作和生活中,每个人都会遭遇高峰和低谷,这是人生的常态。
  • 看着你所失去的,你就会跌入不幸的谷底;看着你所拥有的,你就会处在幸福的高峰。
  • 征服内心的恐惧,就意味着你处在人生的高峰状态。
  • 上天之所以制造苦难,是为了唤醒你的觉知——要关注那些被你忽视的真相。
  • 通过制订愿景来攀登高峰是一个好办法。它能够让你产生一种渴望,并且愿意用自己的行动把愿景变成现实。
  • 从高峰上迅速跌落低谷的原因,往往是不了解真相的骄傲自满;在低谷里无法重新振作的原因,往往是不了解真相的忧虑恐惧。
  • 高峰和低谷不仅是外部的顺境和逆境,更是你内心深处的感觉和变化。
  • 每一个人选择好心态的时候,就意味着他将要离开人生的谷底。
  • 人生的高原期是用来休养生息、深思熟虑和自我更新的时期。
  • 峰谷相连不分。今日顺境之错,换得他日逆境;今日逆境之智,换得他日顺境。

其他

如果有带给你一丝丝小快乐,就让快乐继续传递下去,欢迎转载,点赞,顶,欢迎留下宝贵的意见,多谢支持!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容