50

この質問を投稿してその質問を読ん後、メソッドが null を返すことになっているかどうか、またはこれがエラー状態と見なされて例外をスローする必要があるかどうかを知ることが非常に重要であることに気付きました。'null'を返すか、例外をスローするかについても、適切な議論があります。

メソッドを作成していて、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 でコントラクトを文書化することは決して悪いことではなく、時には役立つこともあります。
  • メソッド名を使用して戻り値のnull可能性を文書化することは、私以外の誰も提案していません。非常に冗長で常に役立つとは限りませんが、それでも利点がある場合があると私は信じています。
4

11 に答える 11

39

非常に良いフォローアップの質問です。私nullは真に特別な値を考えており、メソッドが返す可能性がある場合はnull、それがいつ返されるかを Javadoc に明確に文書化する必要があります ( @return some value ..., or null if ...)。コーディングするとき、私は防御的であり、メソッドが返らnullないと確信していない限り (たとえば、Javadoc がそう言っているため)、メソッドが返される可能性があると想定します。

人々はこれが問題であることを認識しており、提案された解決策は、アノテーションを使用して意図を自動的にチェックできるようにすることです。JSR 305: Annotations for Software Defect DetectionJSR 308: Annotations on Java TypesおよびJetBrain の Nullable How-To を参照してください。

あなたの例は次のようになり、IDE、コンパイラ、またはその他のコード分析ツールによって拒否される可能性があります。

@NotNull
public Object methodWhichCannotReturnNull(int i) throws Exception
{
    return null; // this would lead to a compiler error!
}
于 2009-01-04T18:53:07.020 に答える
9

Option0 個または 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 警告をオンにするか、通常はリテラルを使用するすべての場所nullで使用する場合、コードにまったく表示されないgrep を使用することができます。Option.none()null

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

int x = optionalInt.orSome(0);

そして、これを交換することができます...

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

...これで、もしあなたがOption<String>...

for (String s : myOptionString)
于 2009-01-04T18:45:10.107 に答える
2

IntelliJ IDEA では @Nullable および @NotNull アノテーションがサポートされています。これらのアノテーション (または同様の機能) を Java 7 に追加することについての話もあります。

于 2009-01-04T18:51:50.563 に答える
2

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

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

  1. 言語サポートがそれを表現するのを待ちます (例: C# ?!のこと)
  2. Aspect Orientation を使用して独自の言語拡張機能を構築し、それを表現します
  3. カスタムタイプを使用して表現する
  4. (ただし、開発者の協力に基づいて構築されています)命名スキームを使用してそれを示します
于 2009-01-04T18:53:38.343 に答える
2

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

一方で、null を恐れるものとは考えていないことも認めます。「誰も家にいない」ことが意味のある状況である場合があります (ただし、Null Object テクニックはここでも真の価値があります)。

null 値でメソッド呼び出しを試みると例外が発生することは確かです。しかし、ゼロで割ろうとする試みも同様です。だからといって、ゼロをなくす運動をしなければならないわけではありません! メソッドのコントラクトを理解し、メソッドが返す値を正しく処理する必要があるということです。

于 2009-01-04T20:43:23.020 に答える
1

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

于 2009-01-04T18:43:16.133 に答える
1

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

于 2009-01-04T18:36:36.413 に答える
1

メソッドが次のようになるように、「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>は、戻り値の型として取得していることを知っています)
于 2009-01-04T18:58:48.660 に答える
1

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

于 2009-01-04T20:48:17.147 に答える
0

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

アップデート

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

于 2009-01-04T18:45:37.407 に答える
0

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

そのような方法で API を設計できない場合は、null がいつ、なぜスローされる可能性があるかを明確に文書化します

于 2009-01-04T19:03:15.627 に答える