Comments 26
Проблема для C# актуальна, решается точно так же — аннотациями и статическим анализом (причем в том числе и на основе аннотаций JetBrains).
Optional/scala Option задают контракт более явно.
И не надо никаких обходных маневров. :)
И не надо никаких обходных маневров. :)
Да, ладно… Что мешает в метод, принимающий Optional, передать null вместо экземпляра объекта?
Option в Scala позволяет коду не падать в таких случаях, но и код корректно не будет работать. По своему опыту скажу, что это намного хуже для поиска ошибки.
Как правильно сказано в первом комментарии, главное — этот как раз контракт. Если значения может не быть — делаешь Option. Если видишь Option — готовься к тому, что значения может не быть.
Падать или не падать — вопрос второстепенный. Можно без Option явно проверять все аргументы на null и не падать. Можно наоборот не глядя делать Option.get и падать.
Падать или не падать — вопрос второстепенный. Можно без Option явно проверять все аргументы на null и не падать. Можно наоборот не глядя делать Option.get и падать.
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. Пока так не стал делать, т.к. тестировал. При выполнении задачи переоткрывать проект не нужно — IDEA сама подхватит изменения. Плюс я тут вручную xml правлю, т.к. у меня не получить на таком низком уровне работать с конфигами IDEA в gradle.
Ещё пару замечаний по этим аннотациям и 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 анализ. Правильно? Ну, в смысле, одно из возможностей их использования.
И вообще, кто нибудь работал с ними?
И вообще, кто нибудь работал с ними?
При работе с Java 1.8+ авторы JDT рекомендуют использовать для null-анализа именно type annotations, см. Using null type annotations. См. тж. обсуждение bug 392099.
Аннотации FindBugs не соответствуют этому требованию
А патчик можете написать, чтобы поправить это? Если напишете, закиньте нам в багтрекер. Глядишь, успеем в 3.0.1 протолкнуть.
А, или это чисто эклипсовский баг, а не наш?
Нет, увы.
Насколько я понимаю предметную область, это проблема именно FindBugs,
но Eclipse 4.5+ уже умеет её обходить.
Я постараюсь в ближаёшее время адаптировать аннотации и сообщить Вам.
P. S. Спасибо за отклик =)
Насколько я понимаю предметную область, это проблема именно FindBugs,
но Eclipse 4.5+ уже умеет её обходить.
Я постараюсь в ближаёшее время адаптировать аннотации и сообщить Вам.
P. S. Спасибо за отклик =)
Вам спасибо за статью. К сожалению, поздно увидел.
Насчёт проблемы с полем в Eclipse — проще сразу закинуть поле в локальную переменную, тогда не придётся SuppressWarnings писать:
В таком виде Eclipse ругаться не будет. Тут железобетонно не возникнет проблем даже в условиях высокой конкурентности и при выполнении интерпретируемого фрейма (понятно, что JIT-компилятор сделает то же самое — прочитает поле из кучи только один раз). Ну а ещё проще игнорировать варнинг от эклипса и использовать FindBugs, там null-анализ гораздо мощнее :-)
Насчёт CheckForNull — нам уже написали. К сожалению, это не моя зона ответственности и высоки шансы, что Билл отклонит это. Я в своих проектах сделал так, как по ссылке — сказал эклипсу считать CheckForNull за Nullable и Nullable не использую вообще.
Насчёт проблемы с полем в 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 не использую вообще.
Netbeans 8.0.2 не поддерживает
Я написал патч, посмотрим как пойдет дело дальше
netbeans.org/bugzilla/show_bug.cgi?id=250702
@ParametersAreNonnullByDefault
Я написал патч, посмотрим как пойдет дело дальше
netbeans.org/bugzilla/show_bug.cgi?id=250702
Буквально сегодня закрыли IDEA-76782: Add compiler support for JSR-305 @Nonnull assertions — теперь еще IDEA сможет вставлять в код NotNull assertions, если включена соответсвующая опция для компилятора, учитывая выбранную конфигурацию, а не только jetbrains NotNull
а ещё научились org.springframework.util.Assert обрабатывать: https://youtrack.jetbrains.com/issue/IDEA-159977
Sign up to leave a comment.
Побеждаем NPE hell в Java, не используя IntelliJ IDEA