Pull to refresh

Comments 26

Проблема для C# актуальна, решается точно так же — аннотациями и статическим анализом (причем в том числе и на основе аннотаций JetBrains).
Жаль лишь, что, в отличие от Eclipse, аннотации на пакет целиком (как @NonNullByDefault или @ParametersAreNonnullByDefault) не поддерживаются.
вы уверены? была же доработка и выглядит это теперь так:
с аннотацией @ParametersAreNonnullByDefault
с аннотацией @ParametersAreNullableByDefault
Более того, функциональность, по-видимому, присутствует и в IDEA 13.1.6 (сборка 135.1306)

если я правильно понял, функциональность эта со сборки 134.738
Optional/scala Option задают контракт более явно.
И не надо никаких обходных маневров. :)
Да, ладно… Что мешает в метод, принимающий Optional, передать null вместо экземпляра объекта?
UFO just landed and posted this here
Option в Scala позволяет коду не падать в таких случаях, но и код корректно не будет работать. По своему опыту скажу, что это намного хуже для поиска ошибки.
Как правильно сказано в первом комментарии, главное — этот как раз контракт. Если значения может не быть — делаешь Option. Если видишь Option — готовься к тому, что значения может не быть.

Падать или не падать — вопрос второстепенный. Можно без Option явно проверять все аргументы на null и не падать. Можно наоборот не глядя делать Option.get и падать.
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
У нас тоже аннотации используются — отличная вещь, позволила найти/не допустить несколько ошибок. Плюс это такой зачаток программирования по контракту — когда определяешь метод сразу же аннотируешь возвращаемое значение и входные параметры. И потом проще его писать — не думаешь о том — будет тут null или нет, т.к. всё указано аннотациями плюс IDE проверяет. Ну и использовать этот метод проще — всё помечено аннотациями. Даже бывало укажешь аннотации для метода, а потом смотришь его использование, а там IDE показывает не нужный код — фактически метод возвращает не null, а в местах использования метода проверялось на null и этот код можно сразу удалить :)

Ещё пару замечаний по этим аннотациям и IDEA — у нас на разных проектах разные аннотации использовались в качестве NotNull И Nullable и получается, как только импортируешь проект, нужно не забыть указать эти аннотации в IDEA в качестве аннотаций NotNull и Nullable. Что хоть и не долго но не приятно и иногда забываешь. В общем, для проекта с gradle я сделал такую штуку:

/*
Установить настройки проекта для IDEA. Используется отдельная задача, т.к. задача idea в gradle не поддерживает настройки
проекта, который оформлен в виде директорий (так с 14 IDEA работает). Поэтому нужно править xml файл настроек проекта
отдельно. 
 */
task setupProject << {
    //xml файл настроек IDEA
    File miscXmlFile = new File("./.idea/misc.xml")
    // Если файла нет, то выходим. Нужно, чтобы не было ошибок в Jenkins, когда не создаются IDEA конфигурации.
    if (!miscXmlFile.exists()) {
        return;
    }
    XmlParser xmlParser = new XmlParser()
    Node miscXml = xmlParser.parse(miscXmlFile)
    // Указываем настройки NotNull и Nullable аннотаций для проекта.
    Node nullableNotNullManagerNode = miscXml.component.find { it.@name == "NullableNotNullManager" } as Node
    if (nullableNotNullManagerNode) {
        miscXml.remove(nullableNotNullManagerNode)
    }
    miscXml.append(xmlParser.parseText('''    
        <component name="NullableNotNullManager"> 
          <option name="myDefaultNullable" value="com.my_company.npe.Nullable"/>
          <option name="myDefaultNotNull" value="com.my_company.npe.NotNull"/>
          <option name="myNullables">
            <value>
              <list size="5">
                <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable"/>
                <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable"/>
                <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable"/>
                <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable"/>
                <item index="4" class="java.lang.String" itemvalue="com.my_company.npe.Nullable"/>
              </list>
            </value>
          </option>
          <option name="myNotNulls">
            <value>
              <list size="5">
                <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull"/>
                <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull"/>
                <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull"/>
                <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull"/>
                <item index="4" class="java.lang.String" itemvalue="com.my_company.npe.NotNull"/>
              </list>
            </value>
          </option>
        </component>'''

    ))
    XmlNodePrinter nodePrinter = new XmlNodePrinter(new PrintWriter(new FileWriter(miscXmlFile)));
    nodePrinter.preserveWhitespace = true
    nodePrinter.print(miscXml)
}


Эта задача позволяет автоматически указывать свои аннотации для проекта. Можно добавить её в задачу «idea», чтобы эти аннотации автоматически конфигурировались при загрузки проекта в IDEA. Пока так не стал делать, т.к. тестировал. При выполнении задачи переоткрывать проект не нужно — IDEA сама подхватит изменения. Плюс я тут вручную xml правлю, т.к. у меня не получить на таком низком уровне работать с конфигами IDEA в gradle.
Кстати, вопрос немного в сторону — я только что узнал про type annotations, которые упоминались в статье ( docs.oracle.com/javase/tutorial/java/annotations/type_annotations.html ) Судя по докам, эти аннотации позволяют проще писать nullable анализ. Правильно? Ну, в смысле, одно из возможностей их использования.
И вообще, кто нибудь работал с ними?
Аннотации FindBugs не соответствуют этому требованию

А патчик можете написать, чтобы поправить это? Если напишете, закиньте нам в багтрекер. Глядишь, успеем в 3.0.1 протолкнуть.
А, или это чисто эклипсовский баг, а не наш?
Нет, увы.

Насколько я понимаю предметную область, это проблема именно FindBugs,
но Eclipse 4.5+ уже умеет её обходить.

Я постараюсь в ближаёшее время адаптировать аннотации и сообщить Вам.

P. S. Спасибо за отклик =)
Вам спасибо за статью. К сожалению, поздно увидел.

Насчёт проблемы с полем в Eclipse — проще сразу закинуть поле в локальную переменную, тогда не придётся SuppressWarnings писать:

void doSmth() {
  Object field = this.field;
  if(field == null) {
    return;
  }
  System.out.println(field.hashCode());
}


В таком виде Eclipse ругаться не будет. Тут железобетонно не возникнет проблем даже в условиях высокой конкурентности и при выполнении интерпретируемого фрейма (понятно, что JIT-компилятор сделает то же самое — прочитает поле из кучи только один раз). Ну а ещё проще игнорировать варнинг от эклипса и использовать FindBugs, там null-анализ гораздо мощнее :-)

Насчёт CheckForNull — нам уже написали. К сожалению, это не моя зона ответственности и высоки шансы, что Билл отклонит это. Я в своих проектах сделал так, как по ссылке — сказал эклипсу считать CheckForNull за Nullable и Nullable не использую вообще.
Sign up to leave a comment.

Articles