Подтвердить что ты не робот

Как показать, может ли метод возвращать null

После публикации этот вопрос и читать то один я понял, что очень важно знать, должен ли метод возвращать значение null, или если это считается условием ошибки, и следует исключить исключения. Также есть хорошая дискуссия, когда возвращает 'null или исключение throw.

Я пишу метод, и я уже знаю, хочу ли я вернуть null или исключить исключение, что является лучшим способом выразить свое решение, другими словами, документировать мой контракт?

Некоторые способы, о которых я могу думать:

  • Запишите это в спецификациях/документации (прочитает ли кто-нибудь?)
  • Сделайте это частью имени метода (как я предложил )
  • Предположим, что каждый метод, который генерирует исключение, не будет возвращать null, и каждый, который делает "не", может возвращать null.

В основном я говорю о java, но это может относиться и к другим языкам: почему существует формальный способ выражения, если будут выбраны исключения (ключевые слова throws), но нет формального способа выражения, если 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 никогда не повредит, а иногда даже помогает.
  • Использование имен методов для документирования nullability возвращаемого значения не было предложено кем-либо, кроме меня, и хотя это может быть очень многословным и не всегда полезным, я по-прежнему полагаю, что иногда оно также имеет свои преимущества.
4b9b3361

Ответ 1

Очень хороший следующий вопрос. Я считаю, что null действительно специальное значение, и если метод может вернуться null, он должен четко документировать в Javadoc, когда он это делает (@return some value ..., or null if ...). При кодировании я защищаю и предполагаю, что метод может возвращать null, если я не убежден, что он не может (например, потому что Javadoc сказал так).

Люди поняли, что это проблема, и предлагаемое решение заключается в использовании аннотаций, чтобы заявить о намерении таким образом, чтобы его можно было проверить автоматически. См. JSR 305: Аннотации к обнаружению дефектов программного обеспечения, JSR 308: Аннотации на Java Типы и JetBrain Nullable How-To.

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

@NotNull
public Object methodWhichCannotReturnNull(int i) throws Exception
{
    return null; // this would lead to a compiler error!
}

Ответ 2

Вы можете использовать тип 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();
   }
}

Если вы используете это последовательно, вы можете включить идентификаторы null-предупреждения IDE или просто использовать grep для null, который вообще не должен появляться в вашем коде, если вы используете Option.none() везде, где вы обычно используете null буквальным.

Option поставляется со стандартом Scala, и он называется Maybe в Haskell. Ссылка выше - это библиотека под названием Functional Java, которая включает ее. Эта версия реализует интерфейс Iterable и имеет монадические методы, которые позволяют вам составлять вещи красиво. Например, чтобы обеспечить значение по умолчанию 0 в случае None:

int x = optionalInt.orSome(0);

И вы можете заменить это...

if (myString != null && !"".equals(myString))

... с этим, если у вас есть Option<String>...

for (String s : myOptionString)

Ответ 3

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

Я вижу три варианта:

  • дождитесь поддержки языка для его выражения (например, С#?).
  • используйте Aspect Orientation для создания собственных расширений языка, чтобы выразить это.
  • используйте специальный тип, чтобы выразить его
  • (но основывается на сотрудничестве с разработчиками) использует схему именования, чтобы указать его

Ответ 4

Для Java можно использовать описание метода Javadoc для документирования значения возвращаемого значения, в том числе, может ли оно быть нулевым. Как уже упоминалось, аннотации также могут помочь здесь.

С другой стороны, я признаю, что я не вижу null как нечто, чего можно опасаться. Бывают ситуации, когда "никто дома" не является значимым (хотя метод Null Object также имеет здесь реальную ценность).

Конечно, верно, что попытка вызова метода при нулевом значении вызовет исключение. Но так будет пытаться делить на ноль. Это не значит, что нам нужно продолжать кампанию по ликвидации нулей! Это просто означает, что нам нужно понять контракт по методу и делать правильные вещи со значениями, которые он возвращает.

Ответ 5

Вы видели SpeС#?

Ответ 6

Там некоторая поддержка @Нулевая и @NotNull аннотация в IntelliJ IDEA. Там также есть некоторые разговоры о добавлении этих аннотаций (или аналогичной функции) в Java 7. К сожалению, я не знаю, как далеко это получилось, или если он все еще находится на пути.

Ответ 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 constructed with a null value
   return new NotNull<Object>(null);
}

Это все еще проверка времени выполнения (не время компиляции), но:

  • Он бросил в реализацию метода (это не ошибка в вызывающем коде)
  • Он самодокументируется (вызывающий абонент знает, что получает NotNull<T> как возвращаемый тип)

Ответ 8

Во что бы то ни стало, избегайте использования JavaDocs. Люди читают их только в том случае, если подпись не выглядит тривиальной и самоочевидной (что плохо для начала), и те, кто на самом деле потрудился их читать, с меньшей вероятностью ошибаются с нулями, поскольку в настоящее время они более осторожны,

Ответ 9

Вы можете написать свою собственную аннотацию (Java) или атрибут (С#), чтобы указать, что возвращаемое значение может быть нулевым. Ничто не будет автоматически проверять его (хотя .NET 4.0 будет кодовые контракты для такого рода вещей), но он по крайней мере будет действовать как документация.

Ответ 10

Если вы используете Java 5+, вы можете использовать пользовательскую аннотацию, например. @MayReturnNull

UPDATE

Вся философия кодирования в сторону (возврат null, с использованием исключений, утверждений, yada yada), я надеюсь, что выше ответит на ваш вопрос. Помимо примитивов, имеющих значения по умолчанию, сложные типы могут быть или не быть нулевыми, и ваш код должен иметь дело с ним.

Ответ 11

Вообще говоря, я бы предположил, что значение null возвращается к контракту API по умолчанию. Почти всегда можно создать свой код таким образом, чтобы нулевое значение никогда не возвращалось из ваших API во время "нормального" потока выполнения. (Например, проверьте foo.contains(obj), а затем вызывается foo.get(obj) и имеет отдельную ветвь для нуля. Или используйте Null object шаблон.

Если вы не можете проектировать свой API таким образом, я бы четко документировал, когда и почему можно было бы выбросить нуль - в наименьшее в Javadoc и, возможно, также используя пользовательскую @annotation, такую как предложили несколько других ответов.