【问题标题】:Try Catch Final - final always has null in variable尝试 Catch Final - final 在变量中总是有 null
【发布时间】:2015-09-23 09:11:34
【问题描述】:

我目前的代码存在问题,我无法弄清楚为什么该语句会按原样进行评估。这是我第一次使用 finally 块,所以可能有一些我没有理解的基本行为。

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

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

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

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

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"));
            }
        }
    }
}

编辑我忘了提到,当我说它总是计算为 null 时,我的意思是我的 IDE - Intellij IDEA 警告我 if 条件总是计算为 null。以下是 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,一切似乎都正常。它似乎停止工作的原因是图形服务器超时。

【问题讨论】:

  • 如果resp 始终为空,这表明failSafeGet 总是抛出异常,或者它正在返回null。你有没有隔离其中哪些正在发生?您是否在调试器中单步执行过代码?
  • 当我提到它总是null 时我并不清楚 - IDE 说它总是评估为 null,但在过去的几个月里我一直在使用该方法。代码逻辑有缺陷。谢谢大家的回答
  • “IDE 说它总是计算为 null”是什么意思?哪个IDE?你能写出一个简短但完整表现出相同行为的程序吗?
  • 通过在控制台打印 resp 变量来检查它是否为空

标签: java null try-catch


【解决方案1】:

这是正常行为。这个电话

apiClient.failSafeGet(pageUrl, getRetryCount());

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

【讨论】:

    【解决方案2】:

    在您的代码中:

    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 之前失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-25
      • 1970-01-01
      • 2021-01-12
      • 1970-01-01
      • 2016-08-22
      • 1970-01-01
      相关资源
      最近更新 更多