尝试 Catch Final - final 在变量中总是有 null

Try Catch Final - final always has null in variable

我的代码目前遇到问题,我无法弄清楚为什么要按原样计算此语句。这是我第一次使用 finally 块,所以可能有些基本行为我还没有理解。

此方法的作用是从 api 获取 json 文档并将所述文档存储为 this.thisPage。然后另一种方法 sliceItem 将结果字段拆分为 json 个对象的数组。

只要 API return 的 json 有错误字段(例如,字符串字段存储为 int,或 int 存储为 double 等),就会抛出 MalformedJsonException。这将尝试 10 次(由 failsafeget 处理),如果失败 10 次,则会抛出 MalformedJsonException (RuntimeException)。在这种情况下,我希望 slicePage 做的是获取下一页而不是继续此页面。为简化这一点——每页有 100 个条目;如果偏移量 3500 被破坏,我们想要获得偏移量 3600。

我目前面临的问题是 resp 在最后一个块中总是计算为 null。我不明白为什么会这样,因为 try 块可以 return 除了 null(JSONObject 类型)之外的东西。

任何帮助将不胜感激,如果您需要更多information/code,我愿意提供。

public synchronized void slicePage(){
    JSONObject resp=null; // otherwise java complains that not initialised
    ApiClient apiClient = new ApiClient();
    RestEndPoint pageUrl;
    while (true) {
        pageUrl = getNextPageEndPoint();
        if(pageUrl == null) {
            throw new IllegalStateException("We have reached the end and the code isn't designed to handle the end here"); // we have reached the end
        }
        currentPageNumber++;
        try {
            resp = apiClient.failSafeGet(pageUrl, getRetryCount());
            break;
        }
        catch (MalformedJsonException e) {
            logger.info(String.format("The json was still broken after %d retries. Skipping this page and notifying listeners", getRetryCount()));
            for (Consumer<Integer> consumer: onSkipListenerList) {
                consumer.accept(batchSize); // inform each listener that we are skipping this many entries
            }
        }
        finally { // We need to set the next page end point no matter the outcome of the try catch. N.B. this gets executed even if there is a break
            if(resp == null) {
                // no next possible
                setNextPageEndPoint(null);   // don't consider next; we reached the max
                this.thisPage = null;
            } else {
                if(currentPageNumber > maxPages - 1) {
                    // because a request has been made already, so reduce by 1
                    setNextPageEndPoint(null); // don't consider next; we reached the max
                } else {
                    // else consider next page
                    setNextPageEndPoint(constructNextPageEndPoint(pageUrl, resp));
                }
                this.thisPage = this.parseResult(resp);

                setTotalCount(resp.getInt("totalResults"));
            }
        }
    }
}

EDIT 我忘了说,当我说它总是计算为 null 时,我的意思是我的 IDE - Intellij IDEA 是警告我 if 条件总是计算为空。以下是 Intellij 中显示的帮助(使用 Ctrl-F1)。

 Condition 'resp == null' is always 'true' less... (Ctrl+F1) 
 This inspection analyzes method control and data flow to report possible conditions that are always true or false, expressions whose value is statically proven to be constant, and situations that can lead to nullability contract violations.
 Variables, method parameters and return values marked as @Nullable or @NotNull are treated as nullable (or not-null, respectively) and used during the analysis to check nullability contracts, e.g. report possible NullPointerException errors.
More complex contracts can be defined using @Contract annotation, for example:
@Contract("_, null -> null") — method returns null if its second argument is null @Contract("_, null -> null; _, !null -> !null") — method returns null if its second argument is null and not-null otherwise @Contract("true -> fail") — a typical assertFalse method which throws an exception if true is passed to it 
The inspection can be configured to use custom @Nullable
@NotNull annotations (by default the ones from annotations.jar will be used)

编辑 2 事实证明,代码分析是错误的,值一次非空运行。感谢大家(包括评论员)分享您的见解和建议。最终,我在条件之前插入了一个 logger.info 和值,一切似乎都有效。它似乎停止工作的原因是图形服务器 运行 超时。

这是正常行为。这个电话

apiClient.failSafeGet(pageUrl, getRetryCount());

抛出异常,因此对 resp 的赋值永远不会完成,因此在 finally block 中该值为 null。所以,要么你的方法总是抛出异常,要么,如果没有,它会在某个时候返回 null

在您的代码中:

try {
            resp = apiClient.failSafeGet(pageUrl, getRetryCount());
            break;
        }
        catch (MalformedJsonException e) {
            logger.info(String.format("The json was still broken after %d retries. Skipping this page and notifying listeners", getRetryCount()));
            for (Consumer<Integer> consumer: onSkipListenerList) {
                consumer.accept(batchSize); // inform each listener that we are skipping this many entries
            }
        }
        finally {.....

如果resp = apiClient.failSafeGet(pageUrl, getRetryCount());抛出异常,resp将永远为null,因为程序在将实例赋值给resp之前就失败了