看完这块代码,我久久不能平静 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
ignore
V2EX    程序员

看完这块代码,我久久不能平静

  •  4
     
  •   ignore 2021-04-08 16:26:31 +08:00 12584 次点击
    这是一个创建于 1696 天前的主题,其中的信息可能已经有所发展或是发生改变。

    try { .... if(url == null) { throw new NullPointerException(); } .... } catch (IOException e) { e.fillInStackTrace(); }

    64 条回复    2021-04-09 16:33:25 +08:00
    TmacV2
        1
    TmacV2  
       2021-04-08 16:29:53 +08:00 via iPhone
    为啥
    iRiven
        2
    iRiven  
       2021-04-08 16:31:42 +08:00
    @TmacV2 url 为空的时候直接调用就会抛出 NullPointerException
    ignore
        3
    ignore  
    OP
       2021-04-08 16:34:14 +08:00
    真没想到能遇上这样的代码,以前看着别人的截图也就乐乐
    xuanbg
        4
    xuanbg  
       2021-04-08 16:44:45 +08:00
    这个 catch 是为可能是不合法的或者无法访问的 url 准备的
    misaka19000
        5
    misaka19000  
       2021-04-08 16:45:28 +08:00
    可能是为了方便在 catch 中处理空指针异常
    w4w
        6
    w4w  
       2021-04-08 16:51:10 +08:00
    遇到 NullPointerException,严禁使用 catch 来隐藏编码错误
    LGA1150
        7
    LGA1150  
       2021-0408 17:00:42 +08:00   1
    @w4w #6
    catch 的是 IOException
    pkupyx
        8
    pkupyx  
       2021-04-08 17:01:56 +08:00
    @xuanbg 这个 catch 应该是管网络 IO 不可用的异常
    phpfpm
        9
    phpfpm  
       2021-04-08 17:03:06 +08:00   9
    看完这个帖子,我久久不能平静
    LGA1150
        10
    LGA1150  
       2021-04-08 17:05:46 +08:00   3
    @ignore 能把完整代码贴出来么?显式抛 NPE 很可能是为了快速失败( fail-fast )
    https://stackoverflow.com/questions/45632920/why-should-one-use-objects-requirenonnull/45632988
    ychost
        11
    ychost  
       2021-04-08 17:09:32 +08:00   1
    可能完全是为了终止当前语句块,但是又不想终止方法,可以用下面的骚操作实现:
    do {
    if (url == null) {
    break;
    }

    } while (false)
    unicloud
        12
    unicloud  
       2021-04-08 17:47:16 +08:00
    距离发帖过去 1 小时 20 分钟了,现在心情平静了吗?
    meteor957
        13
    meteor957  
       2021-04-08 17:48:44 +08:00
    现在平静了吗
    altchen
        14
    altchen   2021-04-08 17:51:31 +08:00
    现在平静了吗
    楼主你这么容易激动,对不起你这个 ID 啊。:doge
    tabris17
        15
    tabris17  
       2021-04-08 17:51:39 +08:00   4
    背后的原因让人暖心
    xuanbg
        16
    xuanbg  
       2021-04-08 17:51:46 +08:00
    @pkupyx 对的,url 不为空不代表 url 就正确返回结果,请求出现异常是最正常不过的事情。这时候抛出异常显然不合适,所以要用 try/catch 吃下来 IOException,并通过日志输出异常。
    yeqizhang
        17
    yeqizhang  
       2021-04-08 17:52:41 +08:00
    @LGA1150 #7 赞同这位老哥,这个他手动抛空指针了,后面代码不一定会抛... 所以看情况。这代码确实不太好。11 楼那个看起来更舒服点
    ipwx
        18
    ipwx  
       2021-04-08 17:55:55 +08:00
    我觉得这个代码很好啊(前提是出 null 真是异常而不是预期中的错误)。谁知道我一个 null 放后面的库都会干些啥,到时候真有 null 了都不知道怎么调试。
    wolfie
        19
    wolfie  
       2021-04-08 18:01:38 +08:00
    唯一槽点,扔到了 try 里面。没啥大问题。
    guyeu
        20
    guyeu  
       2021-04-08 18:04:35 +08:00
    感觉没啥毛病啊。。入不合法还不让抛异常了吗
    AoEiuV020
        21
    AoEiuV020  
       2021-04-08 18:07:34 +08:00   1
    没毛病,很可能是等后面自动抛 npe 就晚了,抛异常前已经执行的语句又不能回滚的,
    kincaider
        22
    kincaider  
       2021-04-08 18:12:30 +08:00
    还不平静吗?
    mengkun
        23
    mengkun  
       2021-04-08 18:14:34 +08:00   14
    Kasumi20
        24
    Kasumi20  
       2021-04-08 18:45:54 +08:00
    保护代码在正常条件下执行而已,难道你从来不检查参数的吗
    iseki
        25
    iseki  
       2021-04-08 18:48:04 +08:00 via Android
    我觉得很多时候这是正确的编码方式,Java 里毕竟没有 checkNotNull
    Leviathann
        26
    Leviathann  
       2021-04-08 18:50:52 +08:00 via iPhone   1
    这个就是 guava 的 precondition.checknotnull 吧
    bigbyto
        27
    bigbyto  
       2021-04-08 18:51:14 +08:00 via iPhone
    不是十分的优雅,不过没觉得有太大的问题。
    shm7
        28
    shm7  
       2021-04-08 19:28:13 +08:00 via iPhone
    不晓得♂ 也许是为了把这种业务错误在这个代码块捕捉完也说不定
    TheWidowMaker
        29
    TheWidowMaker  
       2021-04-08 19:38:44 +08:00 via Android
    @guyeu 抛 npe 就很奇怪了吧?
    raaaaaar
        30
    raaaaaar  
       2021-04-08 19:52:21 +08:00
    @mengkun #23 emmmm
    opoojkk
        31
    opoojkk  
       2021-04-08 19:55:26 +08:00
    throw NullPointerException,catch IOException
    LGA1150
        32
    LGA1150  
       2021-04-08 20:08:34 +08:00   2
    @iseki #25
    Objects.requireNonNull
    iseki
        33
    iseki  
       2021-04-08 20:13:33 +08:00
    @LGA1150 thx
    Blessing1
        34
    Blessing1  
       2021-04-08 20:17:17 +08:00
    平常心对待!!!
    Still4
        35
    Still4  
       2021-04-08 20:23:15 +08:00
    代码不全,估摸着 url 来自于其他地方,抛出错误是合理的,抛出 NPE 不合理
    gamexg
        36
    gamexg  
       2021-04-08 20:36:22 +08:00
    非 java 开发
    如果函数参数不允许 null,那么我会在函数开头直接检查
    如果为参数 null,立刻报错并结束函数,防止程序执行一半后碰到空指针错误还要回滚操作。
    另外代码也能够清晰的表明,函数不允许 null 参数。

    不过一般是返回自定义错误,而不是返回 空指针异常
    hhjswf
        37
    hhjswf  
       2021-04-08 22:25:19 +08:00
    俺寻思着,NPE 还用你抛啊
    cgb1021
        38
    cgb1021  
       2021-04-08 22:50:24 +08:00
    是为了把所有错误都放在 catch 里处理
    wutiantong
        39
    wutiantong  
       2021-04-08 22:58:45 +08:00
    搞不懂你们写 java 的点呢[狗头]
    sutra
        40
    sutra  
       2021-04-09 08:42:27 +08:00
    打开 V2EX 我久久不能平静。
    GBdG6clg2Jy17ua5
        41
    GBdG6clg2Jy17ua5  
       2021-04-09 08:47:03 +08:00 via iPhone
    看完代码,我也久久不能平静,写代码怎么了
    szq8014
        42
    szq8014  
       2021-04-09 09:01:26 +08:00
    哈哈,楼主,现在轮到我们久久不能平静了
    CantSee
        43
    CantSee  
       2021-04-09 09:11:44 +08:00
    实习生写的吧
    shutan
        44
    shutan  
       2021-04-09 09:16:44 +08:00
    V 友交流之后应该就平静下来了
    shuqin2333
        45
    shuqin2333  
       2021-04-09 09:22:31 +08:00
    没啥毛病啊
    zm8m93Q1e5otOC69
        46
    zm8m93Q1e5otOC69  
       2021-04-09 09:39:22 +08:00
    没有前面的代码,不知道 try 是为了干什么
    unco020511
        47
    unco020511  
       2021-04-09 09:40:17 +08:00
    非要解释的话也能解释的通,就是能快速把 npe 抛出来,不然还要到真正使用 url 的时候才能抛出 npe,然后 catch ioExcption 这个也没问题,因为 url != null,不代表就不会出现 io 问题
    passerbytiny
        48
    passerbytiny  
       2021-04-09 09:53:23 +08:00 via Android
    passerbytiny
        49
    passerbytiny  
       2021-04-09 09:54:11 +08:00 via Android
    手机操作容易误操作,蛋疼的很,等我再组织回复
    passerbytiny
        50
    passerbytiny  
       2021-04-09 10:07:24 +08:00 via Android
    第一,不含任何信息的 NullPointerException,就算是方法开头的参数检验,看起来也是怪怪的,你哪怕弄个 NullPointException("参数:参数名") 也比这强;或者说,裸参数构造的 NullPointerException 包含的信息量太少,要是未预期的由 JVM 抛出还行,要是主动去抛出就显得很不负责任。

    第二,< try { .... } catch (IOException e) { e.fillInStackTrace(); >,这是明显的吃掉异常的行为,非常新手或者不负责任的行为。
    sdlzqjf
        51
    sdlzqjf  
       2021-04-09 10:15:00 +08:00
    我不明白楼主为啥不能平静,不知道槽点在哪?从写法上来说这段代码值得商榷,但是从执行上来说是没问题的
    NullPointerException 是运行时异常,IOException 非运行时异常,catch IOException 并不会捕捉到 NullPointerException,仍然会抛给上层,执行起来逻辑是没问题的。
    当然,楼主这段代码没有业务逻辑,所以无法判断 throw NullPointerException 是不是合理
    guyeu
        52
    guyeu  
       2021-04-09 10:15:31 +08:00
    @TheWidowMaker #29 java 自带的 Objects.requireNonNull,Guava 的 Preconditions.chechNotNull 都是抛出空指针异常,这俩 API 的设计者都觉得指针是空的抛个空指针就可以,有什么问题呢?
    lachesis
        54
    lachesis  
       2021-04-09 10:40:38 +08:00
    脱离业务上下文单独看,槽点有,但还没到夸张的地步,能用
    gowk
        55
    gowk  
       2021-04-09 10:47:44 +08:00
    @mengkun 你这个图可笑死我了
    Anarchy
        56
    Anarchy  
       2021-04-09 10:50:55 +08:00 via Android
    槽点在哪?空指针问题提前抛出来没啥问题啊。
    hodur
        57
    hodur  
       2021-04-09 10:53:04 +08:00
    不那么好,但又比用到 url 时自动抛出好一点
    SWYou
        58
    SWYou  
       2021-04-09 12:04:38 +08:00 via iPhone
    看了这个帖子以后,我今天也试了试主动抛出 NPE,感觉可有逼格了。
    crclz
        59
    crclz  
       2021-04-09 12:21:54 +08:00
    必须在函数开头检查引用是否为 null,这是最基础的编程常识。这样就可以区分是调用者出了问题,传入了 null,还是函数体有 bug,在中途访问了 null 。bug 就被局限在小范围内,而不是跨函数找 bug 。

    除此之外,没有代码上下文,唯一可能出问题的就是把 IOException 掩盖掉的问题。


    @guyeu C# visual studio 对传入参数的代码建议也包含 if(x == null) throw new NullReferenceException(nameof(x)),和 java 的思想一致。
    nowto
        60
    nowto  
       2021-04-09 13:13:03 +08:00 via Android
    错误要早发现早暴露,能在编译器暴露的,就不要等到运行期。就算运行期也要能早暴露尽早暴露。所以一般会在 public 函数开始处做参数校验,抛出业务相关异常;而且应该尽量在 javadoc 注明某参数不接受 null,会抛什么样的异常。

    如果不做显式校验,而是使用到这个参数时依靠 jvm 自动报错:
    1 、会晚; 2 、是一个业务无关的异常; 3 、随着重构的进行,入参和参数使用的位置可能会很远,甚至不在同一个方法
    justforlook44444
        61
    justforlook44444  
       2021-04-09 14:25:36 +08:00
    姑且不谈 try catch,
    github 上搜索 throw new NullPointerException,代码有 500 万行,其中很多都是这种写法;
    jdk 里面也有这种写法
    jdk/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/dom/DOMSignContext.java
    public DOMSignContext(Key signingKey, Node parent) {
    if (signingKey == null) {
    throw new NullPointerException("signingKey cannot be null");
    }
    if (parent == null) {
    throw new NullPointerException("parent cannot be null");
    }
    setKeySelector(KeySelector.singletonKeySelector(signingKey));
    this.parent = parent;
    }
    所以你不能平静的点在哪里?
    DavidDee
        62
    DavidDee  
       2021-04-09 15:52:05 +08:00
    fail early?
    chinvo
        63
    chinvo  
       2021-04-09 15:56:02 +08:00 via iPhone
    检查参数不应该是在方法开头

    if (url == null) throw new ArgumentNullException(nameof(url));

    privatetan
        64
    privatetan  
       2021-04-09 16:33:25 +08:00
    很多源码不都有这样的判断么
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2696 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 13:46 PVG 21:46 LAX 05:46 JFK 08:46
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86