この質問 を投稿して読んだ後 その1つ メソッドがnullを返すことになっているかどうか、またはこれがエラー条件と見なされ、例外をスローする必要があります。 ‘null’を返すか、例外をスローする を実行するときの良い議論もあります。
私はメソッドを書いていて、nullを返すか例外をスローするかを既に知っています。私の決定を表現する、つまり契約を文書化するための最良の方法は何ですか?
私が考えることができるいくつかの方法:
私は主にJavaについて話していますが、それは他の言語にも当てはまる可能性があります。例外がスローされるかどうかを表す正式な方法(throws
キーワード)があるのに、nullがそうであるかどうかを表す正式な方法がないのはなぜですか返される?
なぜそのようなものがないのですか?
public notnull Object methodWhichCannotReturnNull(int i) throws Exception
{
return null; // this would lead to a compiler error!
}
契約を表現するには多くの方法があります。
@NotNull
のような注釈を使用することをお勧めします。これは、プログラマーに表示され、自動コンパイル時間チェックに使用できるためです。 Eclipseのプラグイン これらのサポートを追加しますが、私には機能しませんでした。Option<T>
やNotNull<T>
のようなカスタムタイプを使用してください。これにより、明確さと少なくともランタイムチェックが追加されます。非常に良いフォローアップの質問。私は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!
}
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)
_
Javaの場合、メソッドのJavadoc記述を使用して、nullにできるかどうかなど、戻り値の意味を文書化できます。すでに述べたように、ここでも注釈が役立ちます。
一方で、ヌルを恐れるべきものとして見ていません。 「誰もいない家」が意味のある状態である状況もあります(ただし、ここではNullオブジェクトテクニックも真の価値があります)。
Null値でメソッドを呼び出そうとすると、例外が発生することは確かです。しかし、ゼロで除算しようとするでしょう。これは、ゼロをなくすためにキャンペーンに参加する必要があるという意味ではありません。これは、メソッドのコントラクトを理解し、返される値を使用して正しいことを行う必要があることを意味します。
実際、フレームワークには「null以外」のポインタ型があり、メソッドが常に値を返すことを示すために返される場合があります。
3つのオプションが表示されます。
どんな犠牲を払っても、JavaDocsに依存することは避けてください。人々がそれらを読むのは、署名が自明で自明ではないように見える場合(そもそも悪いことです)、そして実際にそれらを読むのに苦労している人々は、現在より注意深くなっているため、nullを間違える可能性が低くなります。 。
Spec# をご覧になりましたか?
独自の注釈(Java)または属性(C#)を記述して、戻り値がnullの可能性があることを示すことができます。何も自動的にチェックしません(ただし、.NET 4.0では コードコントラクト がこの種類のものになります)が、少なくともドキュメントとして機能します。
IntelliJ IDEAでは@Nullableおよび@NotNullアノテーション のサポートがいくつかあります。これらの注釈(または同様の機能)を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>
を戻り値の型として)Java 5+を使用している場合は、@ MayReturnNullなどのカスタムアノテーションを使用できます。
[〜#〜]更新[〜#〜]
すべてのコーディング哲学は別として(nullを返す、例外、アサーション、yada yadaを使用)、上記があなたの質問に答えることを願っています。デフォルト値を持つプリミティブとは別に、複合型はnullである場合とnullでない場合があり、コードはそれを処理する必要があります。
一般的に言って、デフォルトではnullの戻り値はAPIの規約に違反していると思います。 「通常の」実行フロー中にAPIからnull値が返されないようにコードを設計することは、ほとんどの場合可能です。 (たとえば、foo.get(obj)を呼び出すのではなく、foo.contains(obj)をチェックして、nullの別のブランチを作成します。または、 Nullオブジェクトパターン を使用します。
このような方法でAPIを設計できない場合は、Javadocでnullがスローされる可能性があるときと理由を明確に文書化しますleast、および他のいくつかの回答が示唆しているようなカスタム@annotationを使用することもできます。