プログラミング未経験で新人研修でプログラミングをやらされている皆様へ（4）

本稿は、[プログラミング未経験で新人研修でプログラミングをやらされている皆様へ（3）](https://qiita.com/tail-island/items/e30c9616bef65e2c36b5)の続きです。

# メソッドを作成して、重複を減らす

でさぁ、ここまでなんとなく書いてきたけど、`System.out.println()`って何なの？　未だに説明がないんだけど。……と、疑問をお持ちの皆様、ついにここで説明します。これはメソッドと呼ばれるもので、それを呼び出しているんです。

## 同じ処理を何回も書くのは苦痛……

こんな計算になんの意味があるのかは分かりませんが、「2と3と5と7と11と13の、それぞれを二乗した結果の合計を求めなさい」というお題のプログラムを考えてみてください。数字の増え方が一定ではないので（あと、配列をまだ勉強していないので）、`for`ループは使用できません。だから、こんなプログラムになります。

~~~java
class SumOfPrimeSquare {
    public static void main(String[] args) {
        int sum = 0;

        sum += 2 * 2;
        sum += 3 * 3;
        sum += 5 * 5;
        sum += 7 * 7;
        sum += 11 * 11;
        sum += 13 * 13;

        System.out.println(sum);
    }
}
~~~

あ、`+=`は、右辺の値を左辺の変数に足し合わせるという意味です。`sum += 2 * 2;`は`sum = sum + 2 * 2;`と同じ結果になります。

で、このプログラムは、2 * 2と書くつもりが2 * 3とか書いちゃいそうで怖いです。だから、変数を使用して間違いが発生する可能性を減らしてみましょう。

~~~java
class SumOfPrimeSquare {
    public static void main(String[] args) {
        int sum = 0;

        int x = 2;
        sum += x * x;

        x = 3;
        sum += x * x;

        x = 5;
        sum += x * x;

        x = 7;
        sum += x * x;

        x = 11;
        sum += x * x;

        x = 13;
        sum += x * x;

        System.out.println(sum);
    }
}
~~~

長いよ！　間違いが発生しづらくはなりましたが、同じ処理を何回も書くのが面倒くさくなってしまいました。`x`に値を設定して、その二乗を計算して`sun`に足し合わせるという処理は、毎回同じですもんね。こんなときは、メソッドが役に立ちます。

## メソッドを作成する

実は今までも皆様はメソッドを作成していて、それは`public static void main(String[] args) {}`の部分です。`main`の部分がメソッドの名前、括弧の中が引数、中括弧の中がメソッドの処理となります……と言われてもなんだかわからないので、具体的なコードで説明とさせてください。

~~~java
class SumOfPrimeSquare {
    public static void main(String[] args) {
        int sum = 0;

        sum += square(2);  // squareメソッドを使用して、2の2乗を足す
        sum += square(3);
        sum += square(5);
        sum += square(7);
        sum += square(11);
        sum += square(13);

        System.out.println(sum);
    }

    // 2乗した結果を返すメソッド
    static int square(int x) {
        return x * x;
    }
}
~~~

今回作成したメソッドは、プログラムの以下の部分です。

~~~java
static int square(int x) {
    return x * x;
}
~~~

メソッドの最初の`static`はとりあえずおまじないだと考えてください（後でクラスと一緒に説明します）。次の`int`は、メソッドで処理をした結果（メソッドの戻り値と呼びます）の型です。今回は`int`の値の2乗を計算するメソッドなので、メソッドで処理をした結果も`int`になりますから、`int`を指定します。`square`はメソッドの名前で、処理内容が分かる名前を自由に付けてください。今回は、二乗を計算するメソッドなので、英訳して`square`にしました。

括弧の中は、メソッドの処理の中で必要となる変数（メソッドの引数と呼びます）を記述します。二乗するにはどの数を二乗するのかという情報が必要なので、`int`型の`x`という変数を書きました。変数なので、名前は何でも構いません。`a`でも`number`でも何でも分かりやすければ可。数学では関数の引数はxとすることが多いので、今回は名前を`x`にしてみました。

中括弧の中が処理です。`x * x`で二乗を計算して、で、計算した結果を関数の処理結果とするために`return`しています。だから中括弧の中は`return x * x;`となったわけですね。

# メソッドを呼び出す

メソッドを作成しただけでは意味がないので、作成したメソッドを利用しましょう。メソッドを利用することを「呼び出す」と言います。

で、メソッドを呼び出しているのは、`sum += square(2);`や`sum += square(3);`の、`square(2)`や`square(3)`の部分です。呼び出される側であるメソッドを作成したときにメソッドの戻り値の型や引数の型を定義したことを、理解力は低いけど記憶力は良いコンピューターは覚えています。だから、メソッドを呼び出すときは型の記述は不要。`メソッド名(引数に代入したい値)`とするだけでオッケーです。

`square(2)`とすると、`square`メソッドの一番目の引数である`int x`に2が代入されます。`int x = 2;`と同じ処理が実行されるわけですね。で、その`x`を使用して`x * x`した結果がメソッドの戻り値として`return`されるので、2の二乗の4になって、それを`sum`に`+=`すれば、これで2の二乗を足し合わせる部分まで終了。あとは続けて`square(3)`や`square(5)`と続けて処理をしていけば完了です。メソッドを使ったら、最初のプログラムより間違いの可能性が減って、2番目のプログラムよりも大分楽になったでしょ？

# メソッド呼び出し時、引数へは値が「代入」される

……どうせなら`sum +=`の部分もメソッドの処理に含めちゃえば楽になるんじゃね？　このようにお考えの方もいらっしゃると思いますが、残念ながらそれはうまくいきません。実際にプログラムを作って試してみましょう。

~~~java
class SumOfPrimeSquare {
    public static void main(String[] args) {
        int sum = 0;

        square(sum, 2);
        square(sum, 3);
        square(sum, 4);
        square(sum, 5);
        square(sum, 11);
        square(sum, 13);

        System.out.println(sum);
    }

    static void square(int sum, int x) {
        sum += x * x;
    }
}
~~~

メソッドは処理結果を返さなくても構いません。で、その場合は、メソッドの戻り値の型を`void`にします。で、足し合わされる数を表現する`int sum`と、二乗して足し合わせる数を表現する`int x`を引数にしてみました。

さて、このプログラムを実行すると……0が表示されてしまいます。あれ？　`sum +=`しているのにどうして？

それは、メソッド呼び出しの際に、引数へは代入がなされるためです。以下のプログラムで考えてみてください。

~~~java
class SumOfPrimeSquare {
    public static void main(String[] args) {
        int i = 0;
        int j = i;

        j += 1;

        System.out.println(i);
        System.out.println(j);
    }
}
~~~

`int i = 0;`で、変数`i`の値は0になります。`int j = i;`では、変数`j`に`i`の値を代入しているので、`j`の値は0になります。で、その後、`j += 1;`で、`j`の値は1を足されて、0 + 1の結果である1になります。ここで重要なのは、変数`j`には変数`i`の「値」が代入されただけで、変数`i`そのものとは無関係であることです。だから、その後の`System.out.println(i);`では`j += 1;`したこととは無関係で、変数`i`の値である0が表示され、`System.out.println(j);`では変数`j`の値である1が表示されます。

考えてみれば当たり前ですよね。代入がこのような動作になっていないと、`int j = i + 1;`と書いたときの動きが、わけわからなくなっちゃいますもん。

で、これは引数でも同じです。`square(sum, 2)`したときの動作は、`square`メソッドの一番目の引数の`sum`に、呼び出し側の`sum`（同じ名前なので分かりづらいですけど、呼び出し側と呼び出される側では同じ名前でも別の変数になります。詳細は、次の章で説明するスコープまでお待ちください）の値を代入し、2番目の引数の`x`に2を代入しています。値が代入されただけなので、呼び出されたメソッドの中で引数の`sum`に`x`を二乗した結果を足し合わせても、呼び出し側の変数`sum`の値は変化しません（先のプログラムで、`j += 1;`しても変数`i`に影響がなかったのと同じ）。

だから、呼び出し側の変数`sum`の値は0のまま変化せず、だから最後の`System.out.println(sum);`で0が表示されたというわけ。

なんでそんな面倒な作りになっているんだと感じた方がいらっしゃるかもしれませんけど、これは、そのような作りの方がプログラミングが楽になるためです。詳細は次の章でご説明しますが、とりあえずは、呼び出される側のメソッドの引数は、呼び出す時に指定した値や変数の値が代入されるだけなのだと覚えておいてください。

ともあれ、その動作を理解してしまえば、メソッドはとても便利です。メソッドを活用したプログラムを作成してみてください。お疲れさまでした。

……ごめんなさい。枕であげた`System.out.println()`について書くのを忘れていました。実はこれ、Javaを作った人が作成してくれたメソッドなんです。今回作成した`square()`メソッドよりちょっと中身は複雑ですけど、でも、同じメソッドなんですよ。我々は、今まで`System.out.println()`でメソッドを呼び出して、画面への表示をしていたわけですな。

プログラミング未経験で新人研修でプログラミングをやらされている皆様へ（5）に続く予定です。