简体   繁体   English

尝试Catch Final-final变量始终为null

[英]Try Catch Final - final always has null in variable

I am currently facing an issue with my code and I can't figure out why this statement is evaluating as it is. 我目前在我的代码中遇到问题,无法弄清楚为什么此语句按原样进行评估。 This is the first time I am using a finally block, so it may be that there is some fundamental behaviour I haven't understood. 这是我第一次使用finally块,因此可能存在一些我不了解的基本行为。

What this method does is it gets a json document from an api and stores said document as this.thisPage . 此方法的作用是从api获取json文档,并将该文档存储为this.thisPage Then another method sliceItem does the splitting of the results field into an array of json objects. 然后另一个方法sliceItem将结果字段拆分为json对象数组。

A MalformedJsonException is thrown whenever the API returns a json that has bad fields (ex. String fields being stored as int, or int as double etc.). 每当API返回包含错误字段的json(例如,将字符串字段存储为int或将int存储为double等)时,都会引发MalformedJsonException。 This is tried 10 times (handled by failsafeget) and if it failed 10 times, MalformedJsonException (RuntimeException) is thrown. 尝试10次(由failsafeget处理),如果失败10次,则抛出MalformedJsonException(RuntimeException)。 What I would like slicePage to do in that case is get the next page instead of continuing with this page. 在这种情况下,我希望slicePage要做的是获取下一页而不是继续此页面。 To simplify this - each page has 100 entries; 为了简化此操作-每个页面有100个条目; if the offset 3500 is broken, we want to get offset 3600. 如果偏移量3500被破坏,我们要获取偏移量3600。

The issue that I am facing currently is that resp always evaluates to null in the final block. 我当前面临的问题是,在最后一个块中, resp总是评估为null I cannot understand why this is the case, since the try block can return something other than null (JSONObject type). 我不明白为什么会这样,因为try块可以返回除null(JSONObject类型)之外的其他值。

Any help would be greatly appreciated and if you need more information/code, I am willing to provide it. 任何帮助将不胜感激,如果您需要更多信息/代码,我愿意提供。

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 I forgot to mention, that when I said it always evaluates to null, I meant that my IDE - Intellij IDEA, is warning me that the if condition always evaluates to null. 编辑我忘了提一下,当我说它总是评估为空时,我的意思是我的IDE-Intellij IDEA警告我if条件总是评估为空。 The following is the help that shows up in Intellij (with Ctrl-F1). 以下是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)

EDIT 2 As it turns out, the code analysis is wrong, the value is non-null once run. 编辑2事实证明,代码分析是错误的,一旦运行该值将为非null。 Thank you everyone (including commentators) for sharing your insights and advice. 感谢所有人(包括评论员)分享您的见解和建议。 Ultimately I inserted a logger.info with the value before the condition and everything seemed to work. 最终,我在条件之前插入了logger.info,其值似乎一切正常。 The reason it seemed to stop working is because the graph server was running into timeouts. 它似乎停止工作的原因是图形服务器已超时。

This is normal behaviour. 这是正常的行为。 This call 这个电话

apiClient.failSafeGet(pageUrl, getRetryCount());

throws the exception, so the value assignment to resp is never completed so in the finally block the value is null. 引发异常,因此对resp的值分配从未完成,因此在finally block该值为null。 So, either you method is always throwing an exception, or, if not, it is returning null at some point. 因此,您的方法总是抛出异常,或者如果不是,则它在某个时刻返回null

In your code: 在您的代码中:

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 {.....

If resp = apiClient.failSafeGet(pageUrl, getRetryCount()); 如果resp = apiClient.failSafeGet(pageUrl, getRetryCount()); throws an exception, resp will be always null, because the program failed before assing the instance to resp. 引发异常,resp始终为null,因为程序在实例实例化之前失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM