2015-09-23 3 views
0

В настоящее время у меня проблема с моим кодом, и я не могу понять, почему этот оператор оценивает как есть. Это первый раз, когда я использую блок finally, поэтому может быть, что есть какое-то фундаментальное поведение, которое я не понял.Try Catch Final - final всегда имеет значение null в переменной

Что делает этот метод, он получает json-документ из api и сохраняет указанный документ как this.thisPage. Затем другой метод sliceItem выполняет разбиение поля результатов на массив объектов json.

Вызов MalformedJsonException генерируется всякий раз, когда API возвращает json с плохими полями (например, строковые поля сохраняются как int или int как double и т. Д.). Это проверено 10 раз (обработано failafeget), и если он провалился 10 раз, бросается MalformedJsonException (RuntimeException). То, что я хотел бы сделать slicePage в этом случае, - это получить следующую страницу, а не продолжать эту страницу. Чтобы упростить это - каждая страница имеет 100 записей; если смещение 3500 нарушено, мы хотим получить смещение 3600.

Проблема, с которой я столкнулся в настоящее время, состоит в том, что resp всегда принимает значение null в последнем блоке. Я не понимаю, почему это так, поскольку блок try может возвращать что-то отличное от нуля (тип 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")); 
      } 
     } 
    } 
} 

EDIT Я забыл упомянуть, что, когда я сказал, что это всегда имеет значение NULL, я имел в виду, что мой IDE - IntelliJ IDEA, предупреждает меня, что если условие всегда имеет значение нуль. Ниже приведена справка, отображаемая в 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 Как выясняется, анализ кода является неправильным, то значение не ноль раз бежать. Спасибо всем (включая комментаторов) за то, что вы делитесь своими знаниями и советами. В конечном итоге я вставил logger.info со значением перед условием, и все, казалось, сработало. Причина, по которой он, казалось, перестает работать, заключается в том, что сервер графов работал с таймаутами.

+1

Если 'resp' всегда равно null, это означает, что либо' failSafeGet' всегда выбрасывает исключение, либо возвращает 'null'. Вы выделили, кто из них происходит? Вы прошли через код в отладчике? –

+0

Когда я упоминал, что это всегда было «null», я был неясно - IDE говорит, что он всегда оценивает значение null, но я использовал этот метод в течение последних нескольких месяцев. Существует недостаток в логике кода.Спасибо всем за ваши ответы. –

+0

Что именно * вы подразумеваете под словом «IDE говорит, что он всегда оценивает значение null»? И какая IDE? Можете ли вы написать короткую, но * полную * программу, которая проявляет такое же поведение? –

ответ

0

Это нормальное поведение. Этот вызов

apiClient.failSafeGet(pageUrl, getRetryCount()); 

бросает исключение, так что присваивание значение resp никогда не завершается так, в finally block значение равно нулю. Таким образом, либо ваш метод всегда бросает исключение, либо, если нет, он возвращает null в какой-то момент.

0

В коде:

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()); выбрасывает исключение, соответственно всегда будет нулевой, так как программа не удалось до того Ассинг экземпляра в соотв.

Смежные вопросы