«Возможно, переменная не инициализирована» Ошибка не указана во время компиляции - PullRequest
0 голосов
/ 14 сентября 2018

При разработке API с использованием SpringBoot мне пришлось сделать QueryBuilder для создания запроса, который может извлекать результаты из базы данных, используя JDBC.

Моя первоначальная структура Query выглядела как

public static class Query {
    private String table;
    private QueryType queryType;
    private List<String> column;
    private List<Fields> where;
    private List<String> groupBy;
    private String orderBy;
    private Map<String,Object> extraFields;
}

Чтобы установить значения в данных полях, я использовал публичные функции, такие как:

public Query addTable(final String tableName){
        this.table = tableName;
        return this;
    }

public Query addExtraField( String key, Object value){
        if(null==this.extraFields)
            extraFields = new HashMap<>();
        this.extraFields.put(key,value);
        return this;
    }

И, наконец, для построения запроса была использована функция с именем toQuery(), которая добавляла различные пункты запроса в одну строку.

toQuery() Функция выглядела следующим образом:

 private static String toQuery(Query query){
    StringBuilder sb = new StringBuilder();
    sb.append(query.queryType.name());
    return sb.toString();
 }

И тогда query был построен с использованием:

QueryBuilder.Query().addTable(sometable).addQueryType(sometype).addExtraFields(somefieldsmap).toQuery();

Однако для некоторых запросов требуется ExtraFields, а для других - нет. Итак, в функции toQuery() я использовал следующий код:

if(query.extraFields()==null || query.extraFields.size()<2){
 // do Something
}

Теперь, мой вопрос заключается в том, почему он не выдавал ошибку во время компиляции, говоря, что я не могу использовать условие .size(), потому что возможно, что extraFields Map не инициализирован в зависимости от того факта, что addExtraFields() был использован или нет. Он продолжал выдавать NullPointerException во время выполнения, когда возникло условие, но не выдавал ошибку во время компиляции, как в следующем простом примере:

 import java.util.*;
 import java.lang.*;
 import java.io.*;
 class Ideone{
     public static void main (String[] args) {
       HashMap<String, String> map;
       boolean temp = false;
       if(temp){map = new HashMap<>();}
       System.out.println(map.size());
    }
 }

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Чтобы ответить на ваш вопрос о том, почему последний блок кода вызывает ошибку компиляции, нам нужно обратиться к Спецификации языка Java :

Для каждого доступа к локальной переменнойили пустое конечное поле x, x должно быть обязательно назначено перед доступом, или произойдет ошибка времени компиляции.

Поскольку переменная map объявлена ​​без инициализации.Инициализация происходит внутри блока if, поэтому компилятор не может определенно узнать, была ли она инициализирована или нет, отсюда и ошибка компиляции.Если вам нужно изменить boolean temp на final и присвоить ему значение true, ошибка компилятора исчезнет, ​​потому что теперь переменная temp является конечной, поэтому компилятор может определить, что блок if должен быть выполнен, а map переменная инициализирована определенно .

0 голосов
/ 14 сентября 2018

Поля класса не нужно явно инициализировать перед использованием. Они неявно инициализируются значением по умолчанию для типа поля:

  • false для типа boolean
  • ноль для простого числового типа
  • null для ссылочного типа.

Вот почему query.extraFields в некоторых случаях null.

Правила для локальных переменных различны, поэтому ваш последний пример - ошибка компиляции. (Согласно правилам JLS с определенным назначением существует путь к вызову println, в котором map, возможно, не было присвоено значение. Поскольку map является локальной переменной, это ошибка компиляции.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...