Как показать, может ли метод возвращать null
после отправки этот вопрос и значение этого я понял, что очень важно знать, должен ли метод возвращать null, или если это считается условием ошибки и должны быть брошены исключения. Существует также хорошая дискуссия, когда возврат ' null’ или исключение throw .
я пишу метод, и я уже знаю, хочу ли я вернуть null или выбросить исключение, каков наилучший способ выразить другими словами, мое решение документировать контракт?
как я могу думать о:
- запишите его в спецификации / документации (кто-нибудь прочитает его?)
- сделать его частью имени метода (как я предложил здесь)
- предположим, что каждый метод, который закидываем исключение не возвращает null, и каждый, кто не бросает может вернуться ноль.
Я в основном говорю о java, но это может относиться и к другим языкам: почему существует формальный способ выражения, если будут брошены исключения (throws
keywords), но нет формального способа выразить, если null может быть возвращен?
почему нет ничего подобного:
public notnull Object methodWhichCannotReturnNull(int i) throws Exception
{
return null; // this would lead to a compiler error!
}
резюме и заключение
есть много способов выразить контракт:
- если ваша IDE поддерживает его (как IntelliJ), это лучше всего использовать аннотацию типа
@NotNull
потому что он виден программисту и может использоваться для автоматической проверки времени компиляции. Есть плагин для Eclipse добавить поддержку для них, но это не сработало для меня. - если это не вариант, используйте пользовательские типы, такие как
Option<T>
илиNotNull<T>
, которые добавляют ясность и, по крайней мере, проверку времени выполнения. - в любом случае, документирование контракта в JavaDoc никогда не повредит, а иногда даже помогает.
- использование имен методов для документирования значения null возвращаемого значения не было предложено никем, кроме меня, и хотя это может быть очень многословно и не всегда полезно, я все еще считаю, что иногда у него есть свои преимущества.
11 ответов
очень хороший вопрос. Я считаю null
особенное значение, и если метод может возвращать null
он должен четко документировать в Javadoc, когда она (@return some value ..., or null if ...
). При кодировании я защищаюсь и предполагаю, что метод может вернуться null
если я не убежден, что это не может (например, потому что Javadoc так сказал.)
люди поняли, что это проблема, и предлагаемое решение заключается в использовании аннотаций для выражения намерения таким образом, чтобы его можно было проверить автоматически. Видеть JSR 305: аннотации для обнаружения дефектов программного обеспечения, JSR 308: аннотации к типам Java и продуктами компании JetBrains как-бы.
ваш пример может выглядеть так и отклонен IDE, компилятором или другими инструментами анализа кода.
@NotNull
public Object methodWhichCannotReturnNull(int i) throws Exception
{
return null; // this would lead to a compiler error!
}
можно использовать Option
тип, который очень похож на список, который имеет ноль или один элемент. Тип возврата Option<Object>
указывает, что метод может возвращать Object
, или он может возвращать специальное значение типа None
. Этот тип является заменой для использования null с лучшими проверками типа.
пример:
public Option<Integer> parseInt(String s) {
try {
return Option.some(Integer.parseInt(s));
}
catch (Exception e) {
return Option.none();
}
}
если вы используете это последовательно, вы можете включить IDE null-warnings или просто использовать grep для null
который не должен появляться в ваш код, если вы используете Option.none()
везде, где вы обычно используете null
литерал.
Option
поставляется стандарт с Scala, и он называется Maybe
в Haskell. Ссылка выше - на библиотеку под названием Функциональная Java, в которую он входит. Эта версия реализует Iterable
интерфейс, и имеет монадические методы, которые позволяют создавать вещи красиво. Например, чтобы обеспечить значение по умолчанию 0 в случае None
:
int x = optionalInt.orSome(0);
и вы можете заменить этот...
if (myString != null && !"".equals(myString))
...с этим, если у вас есть Option<String>
...
for (String s : myOptionString)
Indeed: в нашей структуре у нас есть "ненулевой" тип указателя, который может быть возвращен, чтобы указать, что метод всегда будет возвращать значение.
Я вижу три варианта:
- дождитесь поддержки языка, чтобы выразить его (например,C# ?! вещь)
- используйте ориентацию аспекта для создания собственных расширений языка, чтобы выразить его
- используйте пользовательский тип, чтобы выразить его
- (но основывается на сотрудничестве разработчиков) используйте именование схема его указания
для Java можно использовать описание Javadoc метода для документирования значения возвращаемого значения, в том числе может ли оно быть null. Как уже упоминалось, аннотации могут также оказать здесь помощь.
с другой стороны, я признаю, что не вижу null как чего-то страшного. Есть ситуации, в которых "ничей дом" является значимым условием (хотя техника нулевого объекта также имеет здесь реальную ценность).
Это, безусловно, правда, что попытка вызова метода для значения null вызовет исключение. Но так же будет и попытка деления на ноль. Это не означает, что нам нужно идти в кампанию по устранению нулей! Это просто означает, что нам нужно понять контракт на метод и сделать правильную вещь со значениями, которые он возвращает.
вы можете написать свою собственную аннотацию (Java) или атрибут (C#), чтобы указать, что возвращаемое значение может быть null. Ничто не будет автоматически проверять его (Хотя .NET 4.0 будет иметь контракты кода для такого рода вещей), но он, по крайней мере, будет действовать как документация.
есть некоторая поддержка @Nullable и @NotNull аннотация в IntelliJ IDEA. Есть также некоторые разговоры о добавлении этих аннотаций (или аналогичной функции) в Java 7. К сожалению,я не знаю, как далеко это зашло или все еще на пути.
возможно, вы могли бы определить общий класс с именем "NotNull", чтобы ваш метод мог быть таким:
public NotNull<Object> methodWhichCannotReturnNull(int i) throws Exception
{
// the following would lead to a run-time error thown by the
// NotNull constructor, if it's constructed with a null value
return new NotNull<Object>(null);
}
это все еще проверка времени выполнения (не время компиляции), но:
- он брошен в реализацию метода (это не ошибка в вызывающем коде)
- это самопроверка (звонящий знает, что он получает
NotNull<T>
в качестве возвращаемого типа)
любой ценой избегайте полагаться на JavaDocs. Люди читают их только в том случае, если подпись не кажется тривиальной и самоочевидной (что плохо для начала), и те, кто действительно беспокоится о том, чтобы прочитать их, менее склонны ошибаться с нулями, поскольку в настоящее время они более осторожны.
Если вы используете Java 5+, Вы можете использовать пользовательскую аннотацию, например @MayReturnNull
обновление
вся философия кодирования в сторону (возврат null, использование исключений, утверждений, яда-яда), я надеюсь, что выше ответы на ваш вопрос. Помимо примитивов, имеющих значения по умолчанию, сложные типы могут быть или не быть null, и ваш код должен иметь дело с ним.
вообще говоря, я бы предположил, что возвращаемое значение null по умолчанию противоречит контракту API. Почти всегда можно создать код таким образом, чтобы нулевое значение никогда не возвращалось из API во время "нормального" потока выполнения. (Например, проверьте фу.содержит (obj), а не вызывает foo.get (obj) и наличие отдельной ветви для null. Или используйте Null шаблон объекта.
Если вы не можете создать свой API таким образом, я бы четко документ, когда и почему null может быть брошен--at меньше в Javadoc, и, возможно, также используя пользовательскую аннотацию@, такую как несколько других предложенных ответов.