AxiZ沖縄ブログ

エンジニア育成学校【AxiZ沖縄】のブログです。

Java基礎の補足【メソッド】

メソッドの呼び方

メソッドは、一言でいうと処理をまとめて名前を付けたものです。
このような仕組みは、Jaavに限らず、ほとんどのプログラミンっ言語で用意されています。
ただし、言語によって呼び方が変わる可能性もあるので注意しましょう。
呼び方は言語に様々ですが

  • 関数
  • ファンクション
  • プロシージャ
  • サブルーチン

などの呼び方があります。
同じ言語の中でも、戻り値があるものはファンクション、
戻り値がないものはプロシージャ、
という風に、呼び方を分ける場合もあります。
名前が変わっても基本的な仕組みは同じなので、
Javaでメソッドの概念を理解しておけば、
他の言語を学んだときにも役に立ちます。
メソッドの概念には様々な呼び方があることを知っておきましょう。

済み

可変長の引数

メソッドを定義するときに、可変長の引数というものが定義できます。
これは、引数で受け取る値の数が変わる場合に使用します。
例でみてみます。

public int getSum(int ... num) {
    //
}

このような書き方になります。

(型 ... 変数名)

という風に定義します。
処理の中で引数を使用する場合は、配列として処理します。

public int getSum(int ... num) {
    int sum = 0;
    for(int i = 0; i < num.length; i++) {
        sum += num[i];
    }
    return sum
}

こんな感じです。

getSum(1, 2, 3, 4, 5);

呼び出すときはこんな感じです。
引数の部分にカンマ区切りで値を複数指定できます。

可変長は便利ですが、注意点もいくつかあるので、
それも知っておいてください。

  • 可変長の引数で書けるのは一つだけ

    例えば、こんな風に定義されているメソッドがあったとします。

int getSum(int ... num1, int ... num2) {

}

このとき、以下のような呼び出しを考えてみましょう。

getSum(1, 2, 3, 4, 5);

この場合、num1とnum2の区切りがどこになるのか、
判断することはできません。
なので、このような定義ではコンパイルエラーになります。

  • 可変長の引数は最後に書く必要がある

    例えば、こんな風に定義されているメソッドがあったとします。

// 1
int getSum(int num1, int ... num2) {
    // 処理
}
// 2
int getSum(int ... num1, int num2) {
    // 処理
}

この場合、1の書き方はOKですが、2の書き方ではコンパイルエラーが出ます。

この書き方だと呼び出されたときに不都合がないか?
ということを考えてみると、どのような場合にエラーになるかが覚えやすくなるかもしれません。

再帰呼び出しとスタックオーバーフロー

ここではメソッドの再帰呼び出しについて説明します。

public static int add(int n) {
    n++;
    if (n < 10) {
        n = add(n); //再帰呼び出し
    }
    return n;
}

こんなメソッドがあったとします。
addというメソッド名ですが、
処理の中で、自分自身のメソッドを呼び出しています。
このような呼び出しを、再帰呼び出しと呼びます。

初めて見た時には取っつきにくいと感じる人も多いと思います。
再帰呼び出しの使用頻度はそれほど高くないと思いますが、
並び替え(ソート)など、特定のアルゴリズムではよく使用されます。

同じ処理を繰り返したい、という場合、
真っ先に思い浮かべるのはループ処理ですが、
処理しながらデータの構造が動的に変わっていく場合(並び替えや、木構造に対する処理など)は、
再帰での処理を行った方がシンプルに書けます。

ハノイの塔という有名なパズルがあります。
聞いたこと、見たことのある人も多いでしょう。
ハノイの塔を解くアルゴリズムをプログラムで実装する場合、再帰呼び出しが使われます。
ソースコードもネットで探すと沢山出てくるので、気になった人は調べてみてください。

再帰で注意が必要なのは、書き方によってはエラーが発生してしまう点です。
こんなメソッドがあったとします。

public static int add(int n) {
    n++;
    n = add(n);
    return n;
}

この場合、コンパイルエラーにはなりませんが、
一生return文を通らないことが見て分かります。
この処理を実行すると、スタックオーバーフローという例外が発生します。
(処理が無限に続きますが、無限ループではないという点にも注意)
再帰を使用する際には、正しく処理が終了するように作りましょう。