You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过抛出IllegalArgumentException并捕获以减少代码重复?

API数据处理代码重构问题解答

先看你的问题背景:

我目前有一段处理API数据的循环代码,存在调用processAndStoreData的重复逻辑:

for (int i = 0; i < dataFromApi.size(); i++){ 
    try { 
        returnedPoolData = dataFromApi.get(i).get(); 
        if(returnedPoolData == null || returnedPoolData.getJsonString().isEmpty()) 
            this.processAndStoreData(returnedPoolData, i, calledApis, id, true); 
        else 
            this.processAndStoreData(returnedPoolData, i, calledApis, id, false); 
    } catch (ExecutionException e){ 
        log.info("" + e); 
        this.processAndStoreData(returnedPoolData, i, calledApis, id, true); 
    } 
}

为消除重复,我计划抛出IllegalArgumentException并在catch块中处理,改写后的代码如下:

for (int i = 0; i < dataFromApi.size(); i++){ 
    try { 
        returnedPoolData = dataFromApi.get(i).get(); 
        if(returnedPoolData == null || returnedPoolData.getJsonString().isEmpty()) 
            throw new IllegalArgumentException("Returned data was empty."); 
        else 
            this.processAndStoreData(returnedPoolData, i, calledApis, id, false); 
    } catch (ExecutionException e){ 
        log.info("" + e); 
        this.processAndStoreData(returnedPoolData, i, calledApis, id, true); 
    } 
}

请问该方案是否可行?另外我发现移除ExecutionException后,throw new语句不再出现红色下划线,这是为什么?


一、你的重构方案可行吗?

直接说结论:当前版本的方案不可行,因为它达不到你想要的效果。

你原本的意图是把空数据/空JSON的情况和ExecutionException的情况都统一到调用processAndStoreData(..., true)的逻辑里,但现在的代码有个致命问题:你抛出的IllegalArgumentException是运行时异常,而你的catch块只捕获ExecutionException,所以这个异常会直接向上抛出,导致程序中断,根本不会走到processAndStoreData的错误处理逻辑——完全违背了你的初衷。

如果想用异常的思路来优化,你需要把IllegalArgumentException也加入catch块,比如:

for (int i = 0; i < dataFromApi.size(); i++){ 
    try { 
        returnedPoolData = dataFromApi.get(i).get(); 
        if(returnedPoolData == null || returnedPoolData.getJsonString().isEmpty()) 
            throw new IllegalArgumentException("Returned data was empty."); 
        this.processAndStoreData(returnedPoolData, i, calledApis, id, false);
    } catch (ExecutionException | IllegalArgumentException e){ 
        if (e instanceof ExecutionException) {
            log.info("" + e); 
        }
        this.processAndStoreData(returnedPoolData, i, calledApis, id, true); 
    } 
}

不过更推荐的是不用异常处理预期的业务情况——空数据/空JSON属于你能预见的场景,用布尔变量标记状态会更清晰,代码可读性也更高,还能避免滥用异常:

for (int i = 0; i < dataFromApi.size(); i++){ 
    boolean isErrorCase = false;
    try { 
        returnedPoolData = dataFromApi.get(i).get(); 
        if(returnedPoolData == null || returnedPoolData.getJsonString().isEmpty()) {
            isErrorCase = true;
        } else {
            this.processAndStoreData(returnedPoolData, i, calledApis, id, false);
        }
    } catch (ExecutionException e){ 
        log.info("" + e); 
        isErrorCase = true;
    }
    // 统一处理错误情况
    if (isErrorCase) {
        this.processAndStoreData(returnedPoolData, i, calledApis, id, true);
    }
}

这样既消除了重复代码,逻辑也一目了然,还没有异常带来的额外开销。


二、为什么移除ExecutionException后,throw语句的红色下划线消失了?

这个红色下划线的根源其实不是throw语句本身,而是变量未初始化的编译错误:

在你保留catch (ExecutionException e)的代码里,dataFromApi.get(i).get()可能抛出ExecutionException,这时候returnedPoolData还没被赋值就进入了catch块,而你在catch块里调用processAndStoreData(returnedPoolData, ...)时,Java编译器会报错:这个变量可能还没被初始化。IDE通常会把这个错误标记在try-catch块的相关位置,刚好显示在throw语句附近,所以你看到了红色下划线。

当你移除ExecutionException的catch块后,这个catch块不存在了,也就不会有在catch块里使用未初始化变量的情况,对应的编译错误自然消失,throw语句的红色下划线也就跟着不见了。


内容的提问来源于stack exchange,提问作者Maciaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:06:50