Java入門|メソッドから結果を受け取るしくみ

技を出すだけで終わらない。メソッドから結果を受け取れると、処理はもっと広がる

ここまでで、メソッドには引数を渡して、外から情報を送り込めることを学んできました。たとえば戦士の名前や戦闘力を設定するときには、呼び出し側から値を渡して、その値に応じて処理を変えられましたね。

でもメソッドのやり取りは、呼び出し元からメソッドへ一方通行だけではありません。今度はその逆に、メソッドの側から呼び出し元へ情報を返すこともできます。この「返ってくる値」が戻り値です。

ドラゴンボールでたとえるなら、戦士に「今の戦闘力を教えて」とたずねて、その結果を受け取るようなイメージです。こちらから何かを設定するだけではなく、向こうから状態を返してもらえるようになると、プログラムはぐっと扱いやすくなります。ここでは、戻り値のしくみをドラゴンボールの世界に置きかえながら、やさしく丁寧に整理していきます。

戻り値は、メソッドから呼び出し元へ返される情報

引数は、呼び出し元からメソッドへ値を渡すしくみでした。
戻り値は、その逆です。
メソッドの中で得られた結果を、呼び出し元へ返すためのしくみです。

たとえば、戦士の戦闘力を知りたい場面を考えてみましょう。
戦士オブジェクトの中には power というフィールドがありますが、呼び出し元からその値を取り出して使いたいときがあります。

そんなときに使うのが、たとえば次のようなメソッドです。

int getPower()
{
    System.out.println("戦闘力を調べました。");
    return power;
}

このメソッドでは、

  • 戦闘力を調べたことを表示する
  • 最後に power の値を返す

という動きをしています。

ここで返される power の値が戻り値です。

ドラゴンボールで考える戻り値の感覚

ドラゴンボールで考えると、戻り値はとても自然です。

たとえばスカウターで悟空の戦闘力を確認するとします。
呼び出し元は「戦闘力を知りたい」と思っています。
そこで getPower というメソッドを呼び出すと、メソッドの中で戦闘力が調べられ、その結果が呼び出し元へ返ってきます。

つまり流れとしてはこうです。

  1. 呼び出し元が戦士にたずねる
  2. 戦士が自分の状態を調べる
  3. その結果を呼び出し元へ返す

これは、引数の

  1. 呼び出し元が値を渡す
  2. メソッドがその値を使って処理する

という流れの逆向きです。

この「行きは引数、帰りは戻り値」という感覚をつかめると、とても理解しやすくなります。

戻り値を持つメソッドは、返す値の型を書く

戻り値を使うときには、まず「どんな型の値を返すのか」をメソッドの定義に書きます。

たとえば戦闘力は int 型なので、戦闘力を返すメソッドなら次のようになります。

int getPower()
{
    System.out.println("戦闘力を調べました。");
    return power;
}

ここでの int は、戻り値の型です。
つまりこのメソッドは、int 型の値を返すメソッドだということを表しています。

同じように、名前を返すなら String 型になります。

String getName()
{
    System.out.println("戦士の名前を調べました。");
    return name;
}

このように、戻り値の型は「返したい情報の型」に合わせて決まります。

表で整理するとこうです。

返したい情報戻り値の型
戦士の名前String
戦闘力int

return は「この値を返します」という合図

戻り値を返すときに使うのが return です。

return power;

この1行は、
power の値を呼び出し元へ返します
という意味です。

ここでひとつ大切なのは、return が実行された時点で、そのメソッドの処理はそこで終わるということです。
つまり return は、ただ値を返すだけではなく、メソッドの終了地点でもあります。

今の段階では、まず

  • return のあとに返したい値を書く
  • return が実行されたら、そのメソッドは終わる

この2つを押さえておけば十分です。

戻り値を持つメソッドの例を見る

では、ドラゴンボールのたとえに合わせて、戻り値を持つメソッドを具体的に見てみましょう。

ファイル名:Sample6.java

class Saiyan
{
    String name;
    int power;

    String getName()
    {
        System.out.println("戦士の名前を調べました。");
        return name;
    }

    int getPower()
    {
        System.out.println("戦闘力を調べました。");
        return power;
    }

    void setNamePower(String n, int p)
    {
        name = n;
        power = p;
        System.out.println("戦士の名前を" + name + "に戦闘力を" + power + "にしました。");
    }

    void show()
    {
        System.out.println("戦士の名前は" + name + "です。");
        System.out.println("戦闘力は" + power + "です。");
    }
}

class Sample6
{
    public static void main(String[] args)
    {
        Saiyan goku = new Saiyan();

        goku.setNamePower("悟空", 9000);

        String fighterName = goku.getName();
        int battlePower = goku.getPower();

        System.out.println("サンプルから戦士を調べたところ");
        System.out.println("名前は" + fighterName + "戦闘力は" + battlePower + "でした。");
    }
}

このプログラムでは、Saiyan クラスに

  • getName
  • getPower

という戻り値を持つメソッドがあります。

そして main メソッドでは、その戻り値を変数に代入しています。

getName と getPower の働きを整理する

まず getName を見てみましょう。

String getName()
{
    System.out.println("戦士の名前を調べました。");
    return name;
}

このメソッドの流れはこうです。

  1. 「戦士の名前を調べました。」と表示する
  2. フィールド name の値を返す

つまり、たとえば name に「悟空」が入っていれば、その「悟空」が呼び出し元へ返されます。

getPower も同じです。

int getPower()
{
    System.out.println("戦闘力を調べました。");
    return power;
}

こちらは power の値を返します。
power が 9000 なら、9000 が呼び出し元へ返ります。

呼び出し元では、戻り値を変数に入れて使える

戻り値の便利さは、呼び出し元でその値を受け取って使えるところです。

Sample6.java では次のように書いています。

String fighterName = goku.getName();
int battlePower = goku.getPower();

この2行はとても大事です。

1行目では、goku.getName() が呼び出されます。
すると getName の中で return name; が実行され、戻り値として name の値が返ってきます。
その返ってきた値が、fighterName に代入されます。

2行目でも同じように、goku.getPower() の戻り値が battlePower に代入されます。

表で整理するとこうです。

呼び出し戻ってくる値受け取る変数
goku.getName()name の値fighterName
goku.getPower()power の値battlePower

このように、戻り値は呼び出し元で変数に代入して利用できます。

実行結果を見ると流れがよくわかる

この Sample6.java を実行すると、次のような流れになります。

戦士の名前を悟空に戦闘力を9000にしました。
戦士の名前を調べました。
戦闘力を調べました。
サンプルから戦士を調べたところ
名前は悟空戦闘力は9000でした。

この結果からわかるのは、

  • まず setNamePower で名前と戦闘力を設定している
  • 次に getName と getPower が呼ばれている
  • その戻り値が呼び出し元で使われている

ということです。

つまり、メソッドはただその場で表示して終わるだけでなく、必要な情報を呼び出し元へ持ち帰らせることもできるのです。

戻り値を使わない呼び出しもできる

戻り値があるメソッドは、必ずしもその値を変数に入れなければならないわけではありません。
呼び出すだけで終わらせることもできます。

たとえば、

goku.getPower();

という書き方もできます。

この場合、getPower は呼び出されるので、メソッドの中の処理は実行されます。
ただし、返ってきた戻り値は呼び出し元で特に使っていません。

つまり、

  • 戻り値を変数に代入して使うこともできる
  • 戻り値を使わずに呼び出すこともできる

ということです。

もちろん、せっかく戻り値を返すなら活用したほうが便利な場面は多いですが、この点は知っておくと安心です。

戻り値があるメソッドと、ないメソッドの違い

ここまでで、戻り値を持つメソッドを見てきました。
一方で、戻り値を持たないメソッドもあります。

たとえば setNamePower は戻り値を返しません。

void setNamePower(String n, int p)
{
    name = n;
    power = p;
    System.out.println("戦士の名前を" + name + "に戦闘力を" + power + "にしました。");
}

このようなメソッドでは、戻り値の型のところに void を書きます。

void は、
値を返さない
という意味です。

表で整理するとこうなります。

メソッド戻り値
getNameあり
getPowerあり
setNamePowerなし
showなし

戻り値を返したいなら、返す値に合った型を書く。
返さないなら void を書く。
このルールを押さえておくことが大切です。

void のメソッドは、値を返さずに処理を終える

戻り値のないメソッドでは、最後まで処理が進むとそのまま終わります。
そして呼び出し元へ戻ります。

たとえば setNamePower なら、

void setNamePower(String n, int p)
{
    name = n;
    power = p;
    System.out.println("戦士の名前を" + name + "に戦闘力を" + power + "にしました。");
}

このブロックの終わりまで行けば、それで処理終了です。

また、戻り値のないメソッドでは、何も返さない return を書くこともできます。

void setNamePower(String n, int p)
{
    name = n;
    power = p;
    System.out.println("戦士の名前を" + name + "に戦闘力を" + power + "にしました。");

    return;
}

この return; は、
ここでメソッドを終えて呼び出し元へ戻ります
という意味です。

ただし、今のような単純なメソッドでは、最後までそのまま進めば同じなので、なくても問題ありません。

「引数」と「戻り値」は逆向きのやり取り

ここで一度、引数と戻り値の関係を整理しておくと理解が深まります。

しくみ向き役割
引数呼び出し元 → メソッド値を渡す
戻り値メソッド → 呼び出し元値を返す

たとえば setNamePower は引数を使っています。
これは「名前と戦闘力を渡す」メソッドです。

一方、getName や getPower は戻り値を使っています。
これは「名前や戦闘力を返す」メソッドです。

ドラゴンボールで考えるなら、

  • 引数は「これを設定して」
  • 戻り値は「これが現在の状態です」

というやり取りです。

この対応関係がわかると、メソッドを設計するときに
「この機能は値を受け取るべきか」
「それとも結果を返すべきか」
が考えやすくなります。

この図では、左側にある呼び出しがまず Saiyan クラスのメソッドへ向かっています。
そのあと中央の getName や getPower の中で return が実行され、今度は矢印が右側へ戻っていきます。

この「行って、戻ってくる」流れが、戻り値の本質です。
引数がメソッドへ値を運ぶなら、戻り値はメソッドから結果を持ち帰る役目をしています。

右側に fighterName や battlePower が表示されていることで、返された値が呼び出し元の変数に入って利用されることもわかりやすくなります。

戻り値を使うと、メソッドの結果をあとで使える

戻り値の大きな便利さは、その場で表示して終わりではなく、結果を呼び出し元に持ち帰って自由に使えるところです。

たとえば getPower が 9000 を返したなら、その 9000 を

  • 変数に入れる
  • 表示に使う
  • 別の計算に使う
  • 条件分岐に使う

といった形で活用できます。

今はまだそこまで広げなくて大丈夫ですが、戻り値を使えるようになると、メソッドは単なる表示機能ではなく、結果を生み出す部品として見えてきます。

これはJavaのプログラムを組み立てるうえで、とても大きな一歩です。

いちばん大事な感覚

「メソッドから結果を受け取るしくみ」で大切なのは、次の感覚です。

  • 戻り値は、メソッドから呼び出し元へ返される情報
  • 戻り値を返すメソッドでは、返す値の型を書く
  • return を使って実際の値を返す
  • 戻り値は呼び出し元で変数に代入して使える
  • 戻り値を使わずに呼び出すこともできる
  • 戻り値のないメソッドでは void を使う
  • 引数は値を渡すしくみ、戻り値は値を返すしくみ

ドラゴンボールで言いかえるなら、

  • setNamePower は戦士に情報を与える技
  • getName や getPower は戦士の状態を教えてもらう技
  • こちらから渡すだけでなく、向こうから返してもらうこともできる

ということです。

この感覚がつかめると、メソッドは「処理を実行するだけのもの」から、「結果を返して、呼び出し元と情報をやり取りできるもの」へと見え方が変わってきます。ここまで理解できると、Javaのクラス設計がかなり立体的に見えるようになります。