Previous | Next | Trail Map | Writing Java Programs | オブジェクト、クラス、インタフェース


メソッドへの情報の引き渡し

メソッドを書く時は、そのメソッドが必要とする引数の数と型を宣言する。 メソッドシグニチャで各の引数の型と名前を宣言する。 例えば次は、ローンの合計、金利、ローンの期間、ローンの将来値 などをもとに、住宅ローンの月払いを計算するメソッドである(ローン終了時には買収しているので、おそらくローンの将来値はゼロである)。

double computePayment(double loanAmt, double rate, double futureValue, int numPeriods) {
    double I, partial1, denominator, answer;

    I = rate / 100.0;
    partial1 = Math.pow((1 + I), (0.0 - numPeriods));
    denominator = (1 - partial1) / I;
    answer = ((-1 * loanAmt) / denominator) - ((futureValue * partial1) / denominator);
    return answer;
}

このメソッドでは、 ローンの合計、利率、将来値、年数の4 つの引数を取る。 最初の3つの引数は倍精度浮動小数点数である、4番目は整数である。

このメソッドと同じように、メソッドの引数は、それぞれの変数宣言が型と名前の対になる変数宣言であり、コンマによって区切られる。

type name 

computePayment() メソッドの本体から見て分かるように、引数の値を参照するためには引数名を使用する。

引数の型

Java において、メソッドに正しい Java データ型の引数を渡すことができる。 これには、 computePayment() メソッドで見た double、float、integer のようなプリミティブデータ型とオブジェクトと配列のような参照データ型が含まれる。 ここに引数として配列を認めるコンストラクタの例がある。 この例では、コンストラクタはポイントのリストから新規のPolygonオブジェクトを初期化する(ポイントは x 、 y 座標を表す java.awt パッケージのクラスである)。

Polygon polygonFrom(Point listOfPoints[]) {
    . . .
}

他の言語と異なり、 メソッドをJava メソッドに渡すことができない。 しかしメソッドにオブジェクトを渡して、オブジェクトのメソッドを起動することができる。

引数の名前

Java メソッドに引数を宣言する時は、その引数に名前を提供する。 この名前は項目を参照するためにメソッド本体内で使用される。

メソッド引数はクラスのメンバ変数と同一名を持つことができる。 この場合、引数はメンバ変数を隠すと言われる。 メンバ変数を隠す引数は、クラスを初期化するためにコンストラクタでしばしば使用されている。 次の Circle クラスとそのコンストラクタを例に取る。

class Circle {
    int x, y, radius;
    public Circle(int x, int y, int radius) {
        . . .
    }
}

Circle クラスは 3 つのメンバ変数 x radiusを持っている。 さらに、 Circle クラスのコンストラクタは、引数が初期値を提供するメンバ変数とそれぞれ名前を共有する3つの引数を認める。

引数名はメンバ変数を隠す。 そこでコンストラクタの本体内の x あるいは radius を使用して、メンバ変数ではなく、引数に参照する。 メンバ変数にアクセスするためには、 this − 現在のオブジェクト − を通して参照しなくてはならない。

class Circle { 
    int x, y, radius; 
    public Circle(int x, int y, int radius) {  
        this.x = x;
        this.y = y;
        this.radius = radius;
    } 
}

メソッドの引数は、同じメソッドの別の引数、メソッドへのローカル変数、あるいは同じメソッド内の catch() 節へのパラメータと同じ名前にしてはならない。

値による引き渡し

Java のメソッドでは、メソッドの引数は値により渡される。 起動すると、メソッドは渡された変数の値を受け取る。 例えば、グラフィックスアプリケーションで Pen オブジェクトの現在のカラーを検索しようと試みる以下の Java 文を考慮してみる。

. . .
int r = -1, g = -1, b = -1;
pen.getRGBColor(r, g, b);
System.out.println("red = " + r + ", green = " + g + ", blue = " + b);
. . .

getRGBColor() メソッドが呼び出される時に、変数 g b の値はすべて -1 である。 呼び出し側は getRGBColor() メソッドがg b 変数に現在のカラーの赤、緑、青の値を渡すことを見込んでいる。

しかし、 Java の実行時には getRGBColor() メソッドに変数の値(-1)を渡し、 g b 変数への参照ではない。 それで getRGBColor(-1, -1, -1) のような getRGBColor() への呼び出しと思うだろう。

制御が getRGBColor() メソッドに渡ると、新規のローカル変数がメソッドシグニチャで提供されるパラメータの名前で作成され、メソッドに渡された値で初期化される。

class Pen {
    int redValue, greenValue, blueValue;
    void getRGBColor(int red, int green, int blue) {
        // red, green, and blue have been created and their values are -1
        . . .
    }
}

それで getRGBColor() がそれぞれ red green blue のローカル変数を通して、呼び出し側の rgb の値にアクセスする。 メソッドはローカルに使用するために値の新規のコピーを得る。 それらのローカル変数にされた変更は、呼び出し側からのオリジナルの変数に反映されない。

上記のメソッドシグニチャが暗示する Pen クラスの getRGBColor() の実装を見てみる。

class Pen {
    int redValue, greenValue, blueValue;
    . . .
        // this method does not work as intended
    void getRGBColor(int red, int green, int blue) {
        red = redValue;
        green = greenValue;
        blue = blueValue;
    }
}

このメソッドは作動しないであろう。 制御が次のコードの println() 文に移ると、 getRGBColor() のローカル変数 red green blue はもう存在しない。 それ故に、変数になされた割り当ては効果がなかった。 g b は依然としてすべて -1 である。

. . .
int r = -1, g = -1, b = -1;
pen.getRGBColor(r, g, b);
System.out.println("red = " + r + ", green = " + g + ", blue = " + b);
. . .

値により変数を渡すことは、プログラマに若干の安全性を与える。 メソッドは、その適用範囲以外にある変数を簡単に変更することができない。 しかし、1つあるいは複数の引数を変更することができるメソッドがしばしば必要になる。 getRGBColor() メソッドは好事例である。 呼び出し側はその引数を通して3つの値を返すメソッドを必要とする。 しかし、メソッドはその引数を変更することができず、さらに、メソッドは返り値を通して1つの値を返すことができるだけである。 それでは、どうしたらメソッドが複数の値を返したり、あるいはその適用範囲以外に効果を持つ(若干の値を変更する)ことができるか?

引数を変更するためのメソッドについては、それがオブジェクトあるいは配列のような参照型でなければならない。 オブジェクトと配列も値により渡されるが、オブジェクトの値は参照型である。 結果としては参照型引数は参照によって渡される。 オブジェクトへの参照はメモリにあるオブジェクトのアドレスである。 メソッドのローカル変数は呼び出し側と同じメモリロケーションを参照している。

実際の希望に合わせて、 getRGBColor() メソッドを書き換える。 最初に、新規のオブジェクト RGBColor を導入しなくてはならない。それは RGB スペースで赤、緑、青の値を保持することができる。

class RGBColor {
    public int red, green, blue;
}

引数として RGBColor オブジェクトを認めるように、 getRGBColor() を書き換えることができる。 getRGBColor() メソッドは、RGBColor 引数のredgreen 、そして blue のメンバ変数を設定することにより、ペンの現在のカラーを返す。

class Pen {
    int redValue, greenValue, blueValue;
    void getRGBColor(RGBColor aColor) {
        aColor.red = redValue;
        aColor.green = greenValue;
        aColor.blue = blueValue;
    }
}

最後に、呼び出し順序を書き換える。

. . .

RGBColor penColor = new RGBColor();
pen.getRGBColor(penColor);
System.out.println("red = " + penColor.red + ", green = " + penColor.green + ", blue = " + penColor.blue);
. . .

penColor (呼出し側で)と aColor getRGBColor() メソッドで)が同じオブジェクトを参照するので、 getRGBColor() メソッド内のRGBColor オブジェクトになされた修正は、呼び出し側で作成したオブジェクトに影響を与える。

java.lang パッケージで提供したデータ型ラッパークラス( Float 、 Integer など)は、型がメソッドの引数を通して Java の組み込みプリミティブ型の1つである単独の値を返す場合には特に有用である。


Previous | Next | Trail Map | Writing Java Programs | オブジェクト、クラス、インタフェース