V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NoKey
V2EX  ›  Java

你在 Java 里用 try-catch 多不?

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

    为了避免可能出现的异常

    我们这里大部分方法都用 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,建议再向上层抛出一个定义异常
    oneisall8955
        18
    oneisall8955  
       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   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   1171 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 57ms · UTC 03:42 · PVG 11:42 · LAX 19:42 · JFK 22:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.