web-dev-qa-db-ja.com

Javaに `void`メソッドがあるのはなぜですか?

Javaにvoidメソッドが必要なのはなぜですか? 参照

Voidと宣言されたメソッドは値を返しません。

私が思う限り、voidのすべての使用は、ステータスフラグ、呼び出されているオブジェクト、またはnullを返すことでより適切に処理されます。

これにより、すべての呼び出しが割り当て可能なステートメントになり、ビルダーパターンとメソッドチェーンが容易になります。効果のためにのみ呼び出されるメソッドは、通常、ブール型またはジェネリックSuccess型を返すか、失敗すると例外をスローします。

50
marisbest2

「この関数は成功または失敗する可能性があり、違いを認識できるほど十分に自己認識している」と「この関数の効果についてのフィードバックはありません」には違いがあるためです。 voidがなければ、成功コードを際限なくチェックして、実際にはそのようなことを何もしていないのに、堅牢なソフトウェアを作成していると信じてしまうでしょう。

156
Kilian Foth
  1. Cにはvoid型があり、JavaはC言語ファミリの多くの規則に従うように設計されているためです。
  2. 値を返してほしくない関数がたくさんあります。とにかく「ジェネリックSuccessタイプ」をどうするつもりですか。実際、Javaには例外を示す例外があり、Cにはないため、JavaではCの場合よりも、成功を示す戻り値はそれほど重要ではありません。
94
Mason Wheeler

original言語にvoidタイプがある理由は、Cと同様に、言語の作成者がPascalが行った方法でprocedure sおよびfunction sを使用して言語の構文を不必要に複雑にしたくない。

それが最初の理由でした。

あなたの提案:

ステータスフラグを返す

それはノーノーです。ステータスフラグは使用しません。問題が発生した場合は、例外として報告します。

呼び出されるオブジェクト

呼び出しの流暢なスタイルは最近の発展です。 Javaが作成されたとき、今日も非常に楽しく流暢に使用していて、サポートしていないインターフェースを使用する必要がある場合に目を転がすプログラマーの多くは、生まれもしませんでした。

nullを返す

これは、実際には何も返さないときに、何かを返すものとしてメソッドを宣言することを強制するので、それが何をするのかを理解しようとしているインターフェイスを見ている人にとって非常に混乱するでしょう。人々は必然的に「戻り値なし」を意味する他の役に立たないクラスを発明し、何も返さないすべての関数がそのようなクラスへのnull参照を返すことができるようにします。それは不格好だ。幸いにも、これに対する解決策があります。それはvoidと呼ばれます。そして、それがあなたの質問への答えです。

64
Mike Nakis

System.out.printlnなどの一部のメソッドは、有用なものを返しませんが、この副作用のためにのみ呼び出されます。 voidは、有用な値が返されないことをコンパイラとコードの読者に示す便利なインジケータです。

nullの代わりにvoidを返すことは、この値を何かに使用した瞬間にNullPointerExceptionを取得することを意味します。したがって、コンパイル時エラーと実行時エラーを交換することになります。さらに、戻り値の型をObjectとして定義する必要がありますが、これは紛らわしく、混乱を招きます。 (そして、連鎖はまだ機能しません。)

ステータスコードは通常、エラー状態を示すために使用されますが、Javaにはこの目的で例外があります。

静的メソッドからthisを返すことはできません。

一般的なSuccessオブジェクトを返すことには、有用な目的はありません。

20
JacquesB

1つの理由は、たとえばnull以外のものを返すことが誤解を招くになる可能性があることです。例:

Arrays.sort(a)は何を返す必要がありますか?

呼び出しをチェーンできるようにaを返す必要があると主張する場合(これは質問から判断するとあなたの応答のようです)、戻り値がcopy元のオブジェクト、または元のオブジェクト自体。どちらも可能です。そして、はい、それをドキュメントに入れることもできますが、あいまいさを最初から作成してはならないというのは十分にあいまいです。

一方、nullを返す必要があると主張する場合、戻り値が呼び出し元に提供している可能性のある情報、およびプログラマが_return null_それは情報を伝えません。

そして、あなたがまったくばかげた何か(aの長さなど)を返すと、その戻り値の使用は本当に混乱します-代わりにint len = Arrays.sort(a)と言うのがどれほど混乱するか考えてくださいof _int len = A.length_!

11
user541686

あなたが提案するbooleanと常に等しいtrueを返すことは、無意味である(戻り値に情報がない)だけでなく、実際には誤解を招く可能性があります。ほとんどの場合、実際に利用可能な情報のみを含む戻り値の型を使用するのが最善です。そのため、Javaでboolean for true/falseは、40億の可能な値を持つintを返すのではなく、同様に、可能な値が1つしかない(「一般的な成功」)場合に2つの可能な値を持つbooleanを返します。 、誤解を招くでしょう。

また、不要なパフォーマンスオーバーヘッドが追加されます。

メソッドがその副作用のためだけに使用される場合、返すものはなく、戻り値の型voidはそれを正確に反映します。潜在的なまれなエラーは、例外を介して通知できます。

改善できることの1つは、voidをScalaのUnitなどの実際の型にすることです。これにより、ジェネリックの処理などの問題が解決します。

7

Javaは比較的古い言語です。そして1995年(それが作成されたとき)とその後まもなく、プログラマーは、プロセスがプロセッサを制御するのにかかる時間とメモリの消費量を非常に心配しました。 voidを返すと、戻り値をスタックに置く必要がなく、後でそれを削除する必要がないため、関数呼び出しから数クロックサイクルと少しのメモリ消費が排除されます。

効率的なコードは決して使用しないものを返さないため、無意味な戻り値を持つものにvoidを入れることは、成功値を返すよりもはるかに良い習慣です。

4
The Lazy Coder

私は、2番目のオプション(thisを返す)がvoidではなくアプローチであることを示唆する引数を読みました。これは非常に良いアイデアですが、ビルダースタイルのアプローチは当時は一般的ではありませんでしたJavaが作成されました。当時のように人気があった場合、それはおそらくnullを返すのは非常に悪い考えですIMO。nullがまったく言語にさえなかったらいいのにと思います。

ここで問題となるのは、メソッドがそれ自体の型のインスタンスを返す場合、それが新しいオブジェクトであるか同じオブジェクトであるかが明確でないことです。多くの場合、それは重要ではありません(または重要ではありません)。言語が暗黙的にvoidメソッドでthisを返すように変更できると思います。現時点で私が考えられる唯一の問題は、メソッドが後で同じタイプの新しいオブジェクトを返すように変更された場合、コンパイル警告は表示されませんが、それは大した問題ではないということです。現在の型システムは、これらのタイプの変更を気にしません。これが継承/インターフェースとどのように相互作用するかは、いくつかの考慮が必要ですが、ビルダースタイルのない古いAPIを、まるでそうであるかのように簡単に呼び出すことができます。

2
JimmyJames

別の側面:

Javaは、非常に厳密な機能を備えた静的言語です。これは、他の言語(c/f Ruby、LISPなど)で非常にオープンまたは動的になる多くのものが厳密に決定されることを意味します。

これは一般的な設計上の決定です。 「なぜ」は答えるのが難しいです(まあ、言語の設計者はそれが良いだろうと思ったからです!)。 「目的」はかなり明確です。これにより、コンパイラーはlotのエラーを検出できるようになります。これは、一般的にどの言語にとっても非常に優れた機能です。第二に、言語についての推論が比較的簡単になります。たとえば、Java言語(のサブセット)で証明される正式な正しさを作成するのは比較的簡単です。比較として、それはRubyなどの動的言語では事実上不可能です。

この考え方は言語に浸透します。たとえば、メソッドがスローする可能性のある例外の強制的な宣言、あいまいな多重継承を避けるためのinterfaceclassの別のタイプなどです。それが何であるか(コンパイル時のエラー処理に重点を置いた静的な必須のOOP現実世界の言語)では、これらは実際には非常にエレガントで強力です。それらは、以前に他のどの現実世界の言語よりもこれらの問題のいくつかを探求するためだけに意図的に作られている理論的な(科学的な)言語に近づいています(当時、あなたに気をつけてください)。

そう。厳密なvoidタイプがあることは明確なメッセージです。このメソッドは何も返さず、ピリオドです。それが現実さ。それを強制によって常に何かを返すように置き換えると、はるかに動的な動作が発生します(Rubyのようにevery defは明示的または暗黙的な戻り値を常に持っています)。証明可能性と推論が悪い;または、ここで他のメカニズムを使用して大規模な膨張を行います。

(そして、NB、Ruby(たとえば)はこれを異なる方法で処理し、その解決策はJavaの場合と同様に正確に許容可能です。これは完全に異なる哲学を持っているためです。たとえば、証明可能性をスローしますlargeを使用して、言語の非常に高い表現力に焦点を当てながら、完全に合理化された合理性。)

2
AnoE