你在 Java 里用 try-catch 多不? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NoKey
V2EX    Java

你在 Java 里用 try-catch 多不?

  •  
  •   NoKey 2020-04-16 18:06:35 +08:00 7495 次点击
    这是一个创建于 2009 天前的主题,其中的信息可能已经有所发展或是发生改变。

    为了避免可能出现的异常

    我们这里大部分方法都用 try-catch 括起来

    看起来很难看啊。。。

    比如,接收页面传入的整数,传过来是字符串,我们需要用数字的时候,就会 Integer.valueOf()

    但是,写页面的人不是同一个,也可能经常换,也可能不同项目组

    虽然有文档,但是,不能确保一定会传入整数

    为了在可能出问题的时候不会出问题而背锅,我们就需要用上 try catch

    有大佬会说使用前验证参数

    有时候参很多,每个都去验一次么?

    各位大佬有啥好方法么?

    44 条回复    2020-05-13 18:20:09 +08:00
    FanError
        1
    FanError  
       2020-04-16 18:12:19 +08:00
    现在我都是 throw RuntimeException 了,然后全局异常捕获,统一返回报错信息
    luckyrayyy
        2
    luckyrayyy  
       2020-04-16 18:14:33 +08:00
    楼上+1,直接抛,全局补
    zhuangzhuang1988
        3
    zhuangzhuang1988  
       2020-04-16 18:15:14 +08:00
    <Java8 实战>里这样扯过 P217
    public static Optional<Integer> stringToInt(String s) {
    try {
    return Optional.of(Integer.parseInt(s));
    } catch (NumberFormatException e) {
    return Optional.empty();
    }
    }
    然后再应用

    PS: 其实 C#很早就有函数 tryParse https://docs.microsoft.com/en-us/dotnet/api/system.int32.tryparse?view=netframework-4.8
    yjxjn
        4
    yjxjn  
       2020-04-16 18:17:25 +08:00
    @luckyrayyy 这个全局补怎么说?比如调用某工具类里方法全部抛出异常,然后再调用的 Controller 里面接么?能详细说一下吗?
    luckyrayyy
        5
    luckyrayyy  
       2020-04-16 18:19:35 +08:00
    @yjxjn ExceptionHandler 注解
    asd123456cxz
        6
    asd123456cxz  
       2020-04-16 18:21:19 +08:00
    @yjxjn 如果是 Spring 项目,可以新建一个异常处理类,使用 @ControllerAdvice 注解,默认使用 AOP 构造出针对全部 controller 的代理类,全局处理异常。不过自己写一个切面部分地处理也可以,顺便把日志统计也做了
    Jrue0011
        7
    Jrue0011  
       2020-04-16 18:26:34 +08:00
    Spring MVC 的话,Controller 加 Validated 注解,MVC 本身参数绑定自带的校验再加上校验注解,支持简单参数、Form 对象和 RequestBody 对象,进入方法前入参就校验完了,ControllerAdvice 捕获校验异常统一返回 SmartValidator 格式化后的校验结果,还支持国际化。。。
    superrichman
        8
    superrichman  
       2020-04-16 18:27:13 +08:00 via iPhone
    所有传入的参数都要验证。可以搜搜 java form validation,不需要自己写一堆 try catch
    Jrue0011
        9
    Jrue0011  
       2020-04-16 18:30:30 +08:00
    @Jrue0011 另外这样校验也支持分组。。就是入参是同一个 bean 类,这个接口只校验某几个属性,另一个接口校验另外一些属性
    limuyan44
        10
    limuyan44  
       2020-04-16 18:35:03 +08:00
    全靠全局捕获,自己基本不会用,项目里每个 controller 里面写过 trycatch return 一个自定义 response 我都感觉这帮人没正经学过 spring mvc,框架安排的明明白白的,不需要自己做这种丑陋的写法
    optional
        11
    optional  
       2020-04-16 18:39:01 +08:00 via iPhone
    lombok
    loryyang
        12
    loryyang  
       2020-04-16 19:28:41 +08:00
    Spring MVC 直接支持了啊,都不需要你来处理,包括类型和空判断
    zhuawadao
        13
    zhuawadao  
       2020-04-16 20:18:05 +08:00
    araaaa
        14
    araaaa  
       2020-04-16 22:45:58 +08:00
    let it crash
    xuanbg
        15
    xuanbg  
       2020-04-16 23:01:20 +08:00
    一般都是直接抛,然后全局捕获。只有确定需要处理的异常,才 try/catch 起来自己处理掉异常。譬如处理队列消息的时候,异常了要写回死信队列,以免丢消息。
    paragon
        16
    paragon  
       2020-04-16 23:38:37 +08:00
    关键字 JSR349 ControllerAdvice
    mawerss1
        17
    mawerss1  
       2020-04-16 23:42:46 +08:00 via iPhone   1
    强烈反对上面的把异常 catch 掉返回空值的做法,破坏了语义甚至可能产生一些发现不了的逻辑问题,如果非要 catch,建议再向上层抛出一个定义异常
    itechify
        18
    itechify  
    PRO
       2020-04-17 00:56:03 +08:00 via Android
    这种运行时的,不用管吧,前端传过来错误的,不按照接口定义写,肯定是对方的问题,不是我的问题为啥要管呢
    sagaxu
        19
    sagaxu  
       2020-04-17 01:05:30 +08:00 via Android
    crash early
    crash often
    yanyueio
        20
    yanyueio  
       2020-04-17 07:29:30 +08:00
    和楼上观点大概类似:

    * Java Core: 避开 checked 异常这类编译时就强迫你处理的异常,其他异常 let crash 。
    * 框架: 比如 Spring 系,全局处理,而且搭建架子的负责人应该会提前制定好规范&模板了。

    至于说入参的检验,那要看大家约定的是依靠返回值(json 对象或者其他)来判断还是是依靠抛异常来协商了(类似防御式编程类的官样话),这太灵活了,还是看团队如何约定的。
    orm
        21
    orm  
       2020-04-17 08:10:04 +08:00
    目前我用 try catch 最多的就是在一些定时任务上,避免执行过程终端
    gwybiaim
        22
    gwybiaim  
       2020-04-17 08:37:37 +08:00
    1. Bean Validation(JSR380)
    2. @ControllerAdvice
    3. BizRuntimeException(建议)
    xiaofan2
        23
    xiaofan2  
       2020-04-17 09:40:01 +08:00
    @cshijiel BizRuntimeException 是啥??
    ganning
        24
    ganning  
       2020-04-17 09:46:06 +08:00
    @Validated 可以了解一下这个注解
    kanepan19
        25
    kanepan19  
       2020-04-17 09:47:20 +08:00
    有事务的地方抛异常, 没事务的地方都抓,抓了把异常放到 resultMsg 放到 result 里返回。
    全局异常肯定有,个人不喜欢随便抛。
    chendy
        26
    chendy  
       2020-04-17 09:52:52 +08:00
    工具类里写挺多的,吃掉一些不可能出现的 checked exception (然后抛一个自定义 unchecked exceptoin ),比如加密算法没找到,编码未找到这种…
    yeqizhang
        27
    yeqizhang  
       2020-04-17 10:52:52 +08:00 via Android
    不是用户填的东西的话,没必要,和前端调通了之后一般没有问题,有问题也是要找为啥数据会错。
    如果是用户填的,前端先检验,然后后端也要做检验或者捕获异常,我遇到测试测接口直接传不符合的数据然后提 bug 的
    mosliu
        28
    mosliu  
       2020-04-17 11:03:04 +08:00
    用 common lang3 的 NUmberUtils 的 toInt 不行么? 错误的转出来个默认值 检查直接返回错误。
    aitaii
        29
    aitaii  
       2020-04-17 11:22:27 +08:00
    @xiaofan2 继承 RuntimeException 的自定义业务异常,ExceptionHandler 里处理异常信息
    sunxiansong
        30
    sunxiansong  
       2020-04-17 11:44:57 +08:00
    插一下嘴。。

    之前写 java,try catch 用的不多,反正有毛病都抛出去。

    现在写 go, 各种
    ```go
    if err != nil {
    return err
    }
    ```
    遇到返回结果有 error 的都要这么来一下,复杂点的函数能来好几次

    觉得 java 的话,对于需要特别识别的错误,可以检查下,不然就直接抛出吧,大部分正常流程能走通就行

    有些函数声明的异常甚至几乎不会出现,追求完善的错误处理覆盖是不现实的,还不如完善错误监控处理机制,避免隐式错误处理、错误遗漏,定期的检查错误情况再完善代码

    如果只是不喜欢 try catch 风格,那自己搞一套错误-结果返回方案就行
    EminemW
        31
    EminemW  
       2020-04-17 12:38:05 +08:00
    我有个疑问,这个抛异常会影响性能吗,之前不知道在哪里看过不要随便抛异常。。我的做法的是 return Result.error(code, msg);
    chanchan
        32
    chanchan  
       2020-04-17 12:43:51 +08:00 via Android
    很多地方需要写,但是懒得写
    lihongming
        33
    lihongming  
       2020-04-17 13:43:03 +08:00 via iPhone
    拿异常当日常反馈的路过。

    只要数据不合格就抛异常出去,调用方不 try catch 怎么活啊?
    yukiloh
        34
    yukiloh  
       2020-04-17 15:06:00 +08:00 via Android
    以前自己喜欢扔,后来看到哪里说能抓尽量当下抓,不能的再扔,给搞迷糊了
    purensong
        35
    purensong  
       2020-04-17 15:31:49 +08:00
    定义一个 @ControllerAdvice 修饰的全局异常处理类,实现多个方法加上 @ExceptionHandler(value = Exception.class)
    注解,value 是 Exception 的子类,例如要检查必须的字段传入,用 MethodArgumentNotValidException,具体的字段不能为空用 @NotNull 注解。
    这是通用的异常处理,如果还有业务异常,需要自定义异常类,我习惯直接在代码里抛出自定义异常,也都交由全局异常类去特殊处理
    purensong
        36
    purensong  
       2020-04-17 15:34:07 +08:00
    可以说代码里 try catch 可能都是连接消息关闭,文件不存在这些代码,很少会出现类型检查这种低级别的捕获,这种检查代码大量存在,而且级别较低,不会有出现异常后的处理,基本就是报错提示到前端就没有了。
    pabno
        37
    pabno  
       2020-04-17 16:44:42 +08:00
    1. 从项目整体质量的角度出发,接口约定就应该遵守,如果不是强制约束,即使后端可以兼容这种数据格式,前段指不定也会因为数据格式的不一致而引发新的问题,提前暴露问题会减少修正错误的成本

    2. 后端参数验证可以使用校验框架写表达式自动校验,然后统一捕获校验异常返回统一数据
    xiangyuecn
        38
    xiangyuecn  
       2020-04-17 16:53:10 +08:00
    转换成 int 时,返回 Integer 类型,要么返回一个数要么,返回一个 null,拒绝使用 try catch

    byte 统一用 short 类型,拒绝负数 ( doge
    vwym
        39
    vwym  
       2020-04-17 17:27:32 +08:00
    web 项目就直接抛出去全局处理了,参数验证可以考虑用 Validations 注解完事。
    不做 try catch
    Mystery0
        40
    Mystery0  
       2020-04-18 11:59:38 +08:00 via Android
    @EminemW 确实有一点影响,不过照你的这样子返回 Result.error(code, msg),调用深了以后,每一层都要去做执行结果的判断,写着写着就变成手写 Java 的异常处理机制了
    NoKey
        41
    NoKey  
    OP
       2020-04-20 10:43:30 +08:00
    @pabno 遵守接口约定,按照文档规定写代码,这个要看公司文化,强制执行的的,谁出问题问责谁这没问题,但是有些公司,会把涉及的人都弄出来批一次。。。什么,他传错了参数?他传错参数,你代码不会鉴别?你代码就死在里面了?你这是什么代码?有些公司强绩效,为了不扣分,谨小慎微,尽量避免问题出在自己这一块
    pabno
        42
    pabno  
       2020-04-23 16:15:07 +08:00
    @NoKey 我的意思就是提前校验,让他不能传约定外的参数类型。这种如果客户端传了约定外的类型,那在测试阶段就要把这个问题暴露出来
    notwaste
        43
    notwaste  
       2020-04-29 15:25:13 +08:00
    可以去看下 Hibernate validator
    xinQing
        44
    xinQing  
       2020-05-13 18:20:09 +08:00
    Hibernate validator 校验参数;抛出异常,全局处理。
    同一楼、二楼
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1010 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 18:53 PVG 02:53 LAX 11:53 JFK 14:53
    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