導入
ご存知のとおり、Java はオブジェクト指向プログラミング言語です。つまり、基本的なコンセプトは、基本中の基本は、すべてがオブジェクトであるということです。オブジェクトはクラスを使用して記述されます。
クラスには状態と動作があります。たとえば、銀行口座は、口座内の金額の形で状態を持ち、残高を増減する動作を持つ場合があります。Java の動作はメソッドを使用して実装されます。メソッドの記述方法は、Java 学習の最初の段階で紹介されます。たとえば、Oracle の公式チュートリアル「
メソッドの定義」です。ここには 2 つの重要な側面があります。
- 各メソッドには署名があります。シグネチャはメソッド名とその入力パラメータで構成されます。
- メソッドは戻り値の型を指定する必要があります。
- 戻り値の型はメソッド シグネチャの一部ではありません。
繰り返しますが、これは Java が厳密に型指定された言語であり、コンパイラーは可能な限りどの型がどこで使用されるかを事前に理解したいという事実の結果です。繰り返しますが、私たちを間違いから守るためです。一般に、すべては良いことです。これにより、データを扱う文化が再び私たちに植え付けられたように思えます。したがって、メソッドの場合は値の型が指定されます。また、これと同じ値をメソッドから返すには、キーワードを使用します
return
。
Java のキーワード return ステートメント
ステートメント キーワードは、
return
Oracle チュートリアル「制御フロー ステートメント」で説明されている「
制御フロー ステートメント」を指します。値を返す方法については、公式チュートリアル「
メソッドから値を返す」でも読むことができます。コンパイラは、メソッドから返される値が、メソッドで指定された戻り値の型と一致するかどうかを、可能な限り注意深く監視します。例として、tutorialspoint の
オンライン IDEを使用してみましょう。元の例を見てみましょう。
public class HelloWorld {
public static void main(String []args) {
System.out.println("Hello World");
}
}
ご覧のとおり、ここでメソッドが実行されます
main
。これがプログラムへのエントリ ポイントです。コード行は上から下に実行されます。この
main
メソッドは値を返すことができません。値を返さないと、エラー "
Error: Main method must return a value of type void
" が返されます。したがって、このメソッドは単に画面に出力するだけです。次に、文字列の受信をメッセージを受信するための別のメソッドに移動しましょう。
public class HelloWorld {
public static void main(String []args) {
System.out.println(getHelloMessage());
}
public static String getHelloMessage() {
return "Hello World";
}
}
ご覧のとおり、キーワードを使用して
return
戻り値を指定し、後のメソッドで使用します
println
。メソッドの説明 (定義) では、
getHelloMessage
us を返すことを示しました
String
。これにより、コンパイラはメソッドのアクションが宣言方法と一致しているかどうかをチェックできます。当然のことながら、メソッド定義で指定された戻り値の型は、コードから返される値の型よりも広い場合があります。主なことは、型が相互に縮小されることです。そうしないと、コンパイル時エラー「
error: incompatible types
」が発生します。ところで、おそらくすぐに疑問が生じたと思います。なぜ
return
それがプログラム フロー制御演算子に適用されるのでしょうか? しかし、それはプログラムの上から下への通常の流れを混乱させる可能性があるからです。例えば:
public class HelloWorld {
public static void main(String []args){
if (args.length == 0) {
return;
}
for (String arg : args) {
System.out.println(arg);
}
}
}
この例からわかるように、
main
Java プログラムがパラメータなしで呼び出された場合、メソッドの実行が中断されます。
return
コードを取得するとアクセスできなくなることに注意してください。そして、私たちのスマートコンパイラーはこれに気づき、そのようなプログラムの実行を許可しません。たとえば、次のコードはコンパイルできません。
public static void main(String []args) {
System.out.println("1");
return;
System.out.println("2");
}
これを回避するための汚いハックがあります。たとえば、デバッグ目的やその他の理由です。上記のコードは、ブロック
return
でラップすることで修正できます。
if
if (2==2) {
return;
}
エラー処理での return ステートメント
return
非常に注意が必要な状況が 1 つあります。これをエラー処理と組み合わせて使用できます。すぐに言いたいのですが、ブロック
return
内での使用は
catch
非常に悪い形式なので、避けるべきです。しかし、例が必要ですよね? 彼はこうです。
public class HelloWorld {
public static void main(String []args) {
System.out.println("Value is: " + getIntValue());
}
public static int getIntValue() {
int value = 1;
try {
System.out.println("Something terrible happens");
throw new Exception();
} catch (Exception e) {
System.out.println("Catched value: " + value);
return value;
} finally {
value++;
System.out.println("New value: " + value);
}
}
}
一見すると、
finally
常に実行されるため、2 が返されるはずのように見えます。しかし、いいえ、値は 1 になり、変数への変更は
finally
無視されます。さらに、それに
value
オブジェクトが含まれていて と
finally
述べた場合
value = null
でも、
catch
ではなくオブジェクトへの参照が返されます
null
。しかし、ブロックからは
finally
、オペレーターは
return
正しく機能したはずです。同僚はそのような贈り物に感謝しないことは明らかです。
void.class
そして最後に。のような奇妙な構造を書くことができます
void.class
。なぜ、そして何がポイントなのでしょうか?実際、
Java Reflection APIが使用されるさまざまなフレームワークや難しいケースでは、これが非常に必要になる場合があります。たとえば、メソッドがどの型を返すかを確認できます。
import java.lang.reflect.Method;
public class HelloWorld {
public void getVoidValue() {
}
public static void main(String[] args) {
for (Method method : HelloWorld.class.getDeclaredMethods()) {
System.out.println(method.getReturnType() == void.class);
}
}
}
これは、メソッドの実際のコードを置き換える必要があるテスト フレームワークで役立ちます。ただし、これを行うには、このメソッドがどのように動作するか (つまり、どのような型を返すか) を理解する必要があります。
main
上記のコードから メソッドを実装する 2 番目の方法があります。
public static void main (String[] args) {
for (Method method : HelloWorld.class.getDeclaredMethods()) {
System.out.println(method.getReturnType() == Void.TYPE);
}
}
両者の違いについての興味深い議論は、stackoverflow で読むことができます:
What is theDifference between java.lang.Void and void? #ヴィアチェスラフ
GO TO FULL VERSION