web-dev-qa-db-ja.com

メソッドから明示的にvoidを返すことができないのはなぜですか?

_void run() {
    ...
    if (done) return cancel();
    ...
}
_

ここで、cancel() return void。これはコンパイルされません...そして私はほぼ理由を理解することができます。しかし、ボイドからボイドを返したいのなら、どうしてですか?代わりに、私は次のようなものを書くことになります:

_if (done) {
    cancel();
    return;
}
_

私はコードスタイルの提案を探していません。なぜJavaはこのタイプのvoidリターンを明示的に禁止しているのか知りたいのです。どんな情報でもありがたいです。ありがとう。

55
Travis Webb

式を含むreturnステートメントは、その式の値を返します。 cancel()の型は無効な式です-値を持っていません。

論理的には、cancel()を実行してから、戻り値を返します。これが、あなたが言わなければならないことです。 2つのアクション(cancel()を呼び出してから戻る)は論理的に異なります。

現在、Javacouldは、void-しかし、それは単なる戻り値以上に影響を及ぼします。

24
Jon Skeet

興味深い質問です。 Javaは戻り値の型を強制する(voidは戻り値の型)ので)最初のステートメントは理にかなっているようです。これは慣例としてのみ使用します。void以降はプレースホルダーであり、オブジェクトではありません。言語の一貫性やコンパイラーの単純さのために、おそらく除外することにしました。

から [〜#〜] jls [〜#〜]

式のないreturnステートメントは、キーワードvoidを使用して宣言されたメソッドの本体に、値を返さないように(§8.4)、またはコンストラクターの本体(§8.8)に含める必要があります。

さらに

正確には、式のないreturnステートメントは常に突然完了します。その理由は、値のないreturnです。

25
Johan Sjöberg

それは書くようなものです:

_void v=(void)1; 
return (v);
_

したがって、Javaではvoidtypeではないと思います。

C++では、return cancel();は有効です。

Java)に精通しているC++プログラマーとして、答えは次のとおりです。Java構文では、多くのことがサポートされていません。おそらく単純さや読みやすさのためです。

注:void f()宣言はPascalのprocedure f()宣言に似ており、プロシージャは関数などの値を返すことができなかったため、別のステートメントで呼び出す必要があります。

9
deepmax

voidはタイプではありません。ただし、Voidキーワードの代わりに void タイプを使用すると、コードは機能しますが、次のようになります。手動でreturn nullを入力する必要があります。メソッドからのすべての出口点。

6
michael667

そうしないのでreturnvoidvoidは値ではないため、返すことはできません。

5
Bozho

それはトートロジーです。つまり、voidは、メソッドに戻り値がないことを定義します。したがって、voidがまったく返されない場合、どうすれば「voidを返す」ことができますか?

4
Emoire

短い答え

return cancel()ステートメントは有効な値を返す必要がありますが、メソッド宣言void run()は、run()が値を返さないことを宣言します。したがって、return cancel()run()はエラーです。 returnステートメント(式なし)は、呼び出し元に制御を移そうとし、メソッドの戻り値の型がvoidの場合に使用されます。したがって、エラーではありません。

長い答え

[〜#〜] jls [〜#〜]_The *return* Statement_セクション 状態:

式のないreturnステートメントは、それを含むメソッドまたはコンストラクターの呼び出し元に制御を移そうとします。 [...]式を含むreturnステートメントは、値(§8.4)を返すように宣言されたメソッド宣言に含まれている必要があります。そうしないと、コンパイル時エラーが発生します。式は、あるタイプTの変数または値を示す必要があります。そうでない場合、コンパイル時エラーが発生します。タイプTは、メソッドの宣言された結果タイプに割り当て可能(§5.2)である必要があります。そうしないと、コンパイル時エラーが発生します。

JLS _Method Return Type_セクション 状態:

メソッドの戻り値の型は、メソッドが値を返す場合、メソッドが返す値の型を宣言するか、メソッドが無効であることを示します。戻り値の型R1のメソッド宣言d1は、次の条件が当てはまる場合に限り、戻り値の型R2の別のメソッドd2のreturn-type-substitutableです。[...] * R1が無効の場合、R2は無効です。

JLS _Types, Values, and Variables_章 、最初の段落は次のように述べています。

Javaプログラミング言語は強く型付けされた言語です。つまり、すべての変数とすべての式には、コンパイル時に既知の型があります。型は、変数(§4.12)が保持できる値を制限します。または、式が生成し、それらの値でサポートされる操作を制限し、操作の意味を決定できること。

JLS _The Kinds of Types and Values_セクション 状態:

Javaプログラミング言語には、プリミティブ型(§4.2)と参照型(§4.3)の2種類の型があります。対応して、に格納できる2種類のデータ値があります。引数として渡され、メソッドによって返され、操作される変数:プリミティブ値(§4.2)および参照値(§4.3)。

もう少し引用します。 JLS _Expression Statements_セクション 状態:

CやC++とは異なり、Javaプログラミング言語では、特定の形式の式のみを式ステートメントとして使用できます。Javaプログラミング言語では、 「キャストしてvoid」-voidはタイプではありません

JLS _Method Body_セクション 状態:

メソッドがvoidと宣言されている場合、その本体には、式を含むreturnステートメント(§14.17)を含めることはできません。

そして最後に、JLS _Method Declarations_ section は次のように述べています。

メソッド宣言は、メソッドが返す値のタイプを指定するか、キーワードvoidを使用して、メソッドが値を返さないことを示します。

さて、すべてをつなぎ合わせると、次のことが推測できます。

  • returnステートメントに式が含まれている場合、式は有効な値に評価される必要があります。
  • 有効なreturn式の値は、プリミティブ型または参照型である必要があります。
  • voidは有効な値型ではありません。
  • void戻り値の型で宣言されたメソッドは、値を返しません。
  • メソッドvoid run()は値を返しません。
  • run()では、式なしのreturnは、呼び出し元に制御を喜んで転送します。
  • run()では、_return some expression_は有効な値である必要があり、run()は値を返さないため、_some expression_はエラーです。
3
Dan Cruz

return xは、その型が何であるかに関係なく、明示的に「値xを返す」ことを意味します(もちろん、型は、ステートメントが配置されている関数の戻り値の型と一致する必要があります)。

voidは、厳密に言えば、型のabsenceであり、ひいては値がないため、値を返さないのと同じように、値を返すことは意味がありません。 void変数を宣言する意味があります(許可されていません)。

2
Michael Madsen

ボイドは実際のタイプではありません。 Voidは、メソッド定義の構文をより一貫性のあるものにするための単なるプレースホルダーです。これはJavaイノベーションではありません。これはCから継承されます。

これが、メソッドreturn cancel()voidであっても、コンパイラーがcancel()の記述を許可しない理由です。

1
AlexR

voidはタイプではありません。メソッド定義のvoidは、何も返さないための単なるプレースホルダーです。

1
Sahil Muthoo

面白いアイデア。主な問題は、returnステートメントをreturn <expression>で構成されるものとして定義する言語仕様です。 voidメソッドはnot式であるため、構成は許可されていません。

Voidメソッドを実行してから戻ることで機能を複製できることがわかったので、それを許可する本当の理由はありません。

1
dlev

Java文法 は実際にはメソッド呼び出しのタイプを気にしないので、それは問題ではありません。型チェックシステムでは、チェーンのさらに下流にある必要があります。肝心なのは、ifがreturnキーワードの後に​​文法的にオプションのステートメントが含まれている場合、システムは値が渡されることを期待しているということだと思います。 void確かにタイプですが、タイプvoidの値はありません。

しかし、もちろん、これのどれもあなたの質問への答えを本当に説明しません。ご指摘のとおり、このイディオムを許可すべきではない理由はありません。しかし、それを許可する正当な理由もありません。だから、それはトスです。彼らがやったことをなぜやったのかを合理化しようとすることもできますが、それはおそらく無意味でしょう。

1
acjay

JLSから:

式のないreturnステートメントは、キーワードvoidを使用して宣言されたメソッドの本体に含まれている必要があり、値を返さないか、コンストラクターの本体に含まれている必要があります。

.。

式を含むreturnステートメントは、値を返すように宣言されたメソッド宣言に含まれている必要があります。そうしないと、コンパイル時エラーが発生します。式は、あるタイプTの変数または値を示す必要があります。そうでない場合、コンパイル時エラーが発生します。タイプTは、メソッドの宣言された結果タイプに割り当て可能である必要があります。そうしないと、コンパイル時エラーが発生します。

1

これを処理する適切な方法は次のとおりです。

void run() {
...
if (done) {
    cancel();
    return;
    }
...
}
0
djhaskin987