web-dev-qa-db-ja.com

メソッドがnullを返すかどうかを示す方法

この質問 を投稿して読んだ後 その1つ メソッドがnullを返すことになっているかどうか、またはこれがエラー条件と見なされ、例外をスローする必要があります。 ‘null’を返すか、例外をスローする を実行するときの良い議論もあります。

私はメソッドを書いていて、nullを返すか例外をスローするかを既に知っています。私の決定を表現する、つまり契約を文書化するための最良の方法は何ですか?

私が考えることができるいくつかの方法:

  • 仕様書/ドキュメントに書き留めてください(誰でも読んでくれますか?)
  • メソッド名の一部にする(私が提案したように here
  • throws例外であるすべてのメソッドがnotを返し、nullをスローしないすべてのメソッドがmightで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を文書化することは、私以外の誰も提案しませんでした。非常に冗長であり、必ずしも役立つとは限りませんが、利点があることもあると思います。
45
Lena Schimmel

非常に良いフォローアップの質問。私は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!
}
36
Ronald Blaschke

Option タイプを使用できます。これは、要素が0個または1個のリストと非常によく似ています。戻り値の型_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をオンにするか、nullに対してgrepを使用するだけです。これは、Option.none()通常、nullリテラルを使用するすべての場所。

OptionはScalaに標準で付属しており、HaskellではMaybeと呼ばれています。上記のリンクは Functional Java と呼ばれるライブラリを含み、それを含みます。そのバージョンはIterableインターフェイスを実装し、物事をうまく構成できるモナディックメソッドを持っています。たとえば、Noneの場合にデフォルト値0を提供するには:

_int x = optionalInt.orSome(0);
_

そして、あなたはこれを置き換えることができます...

_if (myString != null && !"".equals(myString))
_

...これで、_Option<String>_がある場合...

_for (String s : myOptionString)
_
8
Apocalisp

Javaの場合、メソッドのJavadoc記述を使用して、nullにできるかどうかなど、戻り値の意味を文書化できます。すでに述べたように、ここでも注釈が役立ちます。

一方で、ヌルを恐れるべきものとして見ていません。 「誰もいない家」が意味のある状態である状況もあります(ただし、ここではNullオブジェクトテクニックも真の価値があります)。

Null値でメソッドを呼び出そうとすると、例外が発生することは確かです。しかし、ゼロで除算しようとするでしょう。これは、ゼロをなくすためにキャンペーンに参加する必要があるという意味ではありません。これは、メソッドのコントラクトを理解し、返される値を使用して正しいことを行う必要があることを意味します。

2
joel.neely

実際、フレームワークには「null以外」のポインタ型があり、メソッドが常に値を返すことを示すために返される場合があります。

3つのオプションが表示されます。

  1. 言語サポートがそれを表現するのを待ちます(例 C#?! こと)
  2. アスペクトオリエンテーションを使用して独自の言語拡張を構築し、それを表現する
  3. カスタムタイプを使用して表現する
  4. (ただし、開発者の協力の上に構築されています)命名スキームを使用してそれを示します
2
xtofl

どんな犠牲を払っても、JavaDocsに依存することは避けてください。人々がそれらを読むのは、署名が自明で自明ではないように見える場合(そもそも悪いことです)、そして実際にそれらを読むのに苦労している人々は、現在より注意深くなっているため、nullを間違える可能性が低くなります。 。

1
Uri

Spec# をご覧になりましたか?

1
Ray Booysen

独自の注釈(Java)または属性(C#)を記述して、戻り値がnullの可能性があることを示すことができます。何も自動的にチェックしません(ただし、.NET 4.0では コードコントラクト がこの種類のものになります)が、少なくともドキュメントとして機能します。

1
Jon Skeet

IntelliJ IDEAでは@Nullableおよび@NotNullアノテーション のサポートがいくつかあります。これらの注釈(または同様の機能)をJava 7.に追加することについての話もいくつかあります。残念ながら、それがどれだけ進んだか、それがまだ順調に進んでいるかどうかはわかりません。

1
Joachim Sauer

「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>を戻り値の型として)
1
ChrisW

Java 5+を使用している場合は、@ MayReturnNullなどのカスタムアノテーションを使用できます。

[〜#〜]更新[〜#〜]

すべてのコーディング哲学は別として(nullを返す、例外、アサーション、yada yadaを使用)、上記があなたの質問に答えることを願っています。デフォルト値を持つプリミティブとは別に、複合型はnullである場合とnullでない場合があり、コードはそれを処理する必要があります。

0
opyate

一般的に言って、デフォルトではnullの戻り値はAPIの規約に違反していると思います。 「通常の」実行フロー中にAPIからnull値が返されないようにコードを設計することは、ほとんどの場合可能です。 (たとえば、foo.get(obj)を呼び出すのではなく、foo.contains(obj)をチェックして、nullの別のブランチを作成します。または、 Nullオブジェクトパターン を使用します。

このような方法でAPIを設計できない場合は、Javadocでnullがスローされる可能性があるときと理由を明確に文書化しますleast、および他のいくつかの回答が示唆しているようなカスタム@annotationを使用することもできます。

0
Ross