Как настроить Eclipse (Java) для распознавания пользовательского утверждения при проверке потенциального нулевого указателя

У меня есть следующий фрагмент кода Java:

public void silence(final Object key) {
    final Chain chain = (Chain)getChain(key);
    checkPrecondition(chain != null);
    chain.silence();
  }

Вызов checkPrecondition вызывает исключение времени выполнения, если цепочка имеет значение null, но Eclipse, похоже, не «понимает это»: он говорит, что chain.silence() - это возможный доступ к нулевому указателю (предупреждение). Вопрос: Как я могу «сказать» Eclipse, что checkPrecondition() гарантирует, что цепочка не равна нулю, т. е. имеет характер утверждения? Я знаю, что могу отключить это предупреждение, но я бы не стал этого делать, потому что в других ситуациях это может быть оправдано.

Интересно, что когда я удаляю вызов checkPrecondition(), предупреждение исчезает (именно в этом случае я и ожидал его увидеть).

Я использую Eclipse 4.4.2 (32-разрядная версия) в Windows. Java VM 1.3 (!). Обновление до более новых версий в настоящее время невозможно.


person FreeSpirit64    schedule 19.07.2017    source источник
comment
Несвязанный: поскольку вы беспокоитесь о качестве кода... подумайте, действительно ли вы хотите следовать этому уродливому подходу с размещением final везде. То, что цепочка является конечной, добавляет нулевое значение этому методу. Это просто линейный шум, не имеющий реальной цели.   -  person GhostCat    schedule 19.07.2017
comment
В этом случае использование final, по общему признанию, имеет ограниченную пользу, но также не требует затрат. Так что вообще никаких потерь. В других контекстах использование final сообщает о намерениях программиста и может привести к обнаружению ошибок кодирования во время компиляции, а не при утомительном тестировании. Наше руководство по кодированию явно требует использования final, как и большинство современных и серьезных руководств по кодированию, которые я видел. Очень высокая выгода!   -  person FreeSpirit64    schedule 21.07.2017
comment
И из-за этого разработчики языка Java потратили драгоценное время на улучшение компилятора для эффективного обнаружения переменных final, чтобы вам не приходилось записывать final для локальных переменных, которые впоследствии не изменяются ;- ) ... и как вы меня заинтересовали: можете привести примеры ссылок?   -  person GhostCat    schedule 21.07.2017


Ответы (1)


Вы не говорите Eclipse, что вы должны создать код с таким синтаксисом и логикой, которые компилятор Java будет успешно компилировать и что JVM сможет выполнить.

Это нормально, что возникает исключение во время выполнения. Значение переменной может быть проверено только во время выполнения, то же самое для нулевого указателя (на самом деле это имеет место почти в каждом языке, притворяющемся исходящим из C и использующим что-то, связанное с указателями, и это уже имело место до C).

Вы можете решить эту проблему, используя два разных подхода, в зависимости от вашего стиля и того, который используется в вашем проекте.

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

    public void silence(final Object key) {
    
        if (key == null) {
            throw new IllegalArgumentException("Key should not be null.");
        }
    
        Object oChain = getChain(key);
    
        if (oChain == null || !(oChain instanceof Chain)) {
            throw new IllegalArgumentException("Key should be mapped to an object from the Chain class type.");
        }
    
        Chain chain = (Chain)oChain;
        if(checkPrecondition(chain)) {
             chain.silence();
        }
    }
    
  • Второй способ оскорбителен: вызывающий код должен обрабатывать это, и подпроцесс не должен ничего рушить!

    public boolean silence(final Object key) {
        if (key == null) return false;
        Object oChain = getChain(key);
        if (oChain == null || !(oChain instanceof Chain)) return false;
        Chain chain = (Chain)oChain;
        if(!checkPrecondition(chain)) return false;
        chain.silence();
        return true;
    }
    

Обратите внимание: я предполагаю, что метод checkcondition возвращает логическое значение и что его единственный аргумент должен быть объектом из класса Chain.

person Alex C.    schedule 19.07.2017
comment
Я ценю, что вы нашли время, чтобы ответить, большое спасибо. Однако я не вижу ответа на свою проблему. Проблема в том, что при наличии вызова checkPrecondition() Eclipse жалуется, хотя проблемы нет (обрабатывается нулевой регистр). Если вызов не на месте, есть проблема (нулевой случай не обрабатывается), но Eclipse не жалуется. Существенное увеличение размера кода в соответствии с вышеизложенным в нашем случае неприемлемо. С другой стороны, ваш намек на проверку не только на null, но и на instanceof хорошо принят. - person FreeSpirit64; 21.07.2017
comment
Что я имею в виду под сообщением Eclipse, так это: PC lint, например, позволяет мне заявить, что определенное пользовательское выражение действует как утверждение и должно рассматриваться как синоним утверждения во время статического анализа кода. Это имеет большой смысл, и это то, что я ищу в Eclipse. - person FreeSpirit64; 21.07.2017
comment
С моей версией: без нареканий. Ну, я понимаю, что вы запутались, но ваш код, похоже, вообще не компилируется (особенно вызов checkPrecondition вызывает то, что вы передаете логическое значение там, где ожидается другой тип, по крайней мере, я на это надеюсь). Обычно вы просто не пытаетесь модифицировать Eclipse Linter, который, вероятно, является одним из самых больших помощников, которые вы когда-либо получали (парни, стоящие за этим, очень хорошие программисты, и вы можете им доверять). Если вы это сделаете, вам больше не понадобится Eclipse. Обновлять код гораздо проще, чем модифицировать сам Eclipse: представьте, что модифицируете линтер при каждом обновлении или появлении нового проекта. - person Alex C.; 21.07.2017