dx=(p1.x-p2.x);dy=(p1.y-p2.y);
r=Math.sqrt(dx*dx+dy*dy);
のp1 -> p2, p2-> p3と置き換えると,p2とp3の距離を求める部分である,
dx=(p2.x-p3.x);dy=(p2.y-p3.y);
r=Math.sqrt(dx*dx+dy*dy);
になる.このように「変数の置き換えをすれば同じになる部分」を抜き出して,
一カ所で書けるようにしたものが,静的メソッド呼び出しである.Basicなど
のサブルーチン,C言語での関数などにあたる.
public static 返り値の型 メソッド名(引数宣言){
メソッド本体
}
のように書いて宣言する.「変数の置き換え」にあたる部分を宣言するのが,
引数(ひきすう)宣言部である.
置き換えたい部分,
dx=(p1.x-p2.x);dy=(p1.y-p2.y);
r=Math.sqrt(dx*dx+dy*dy);
で,変数 p1, p2 は値を参照されるだけなので,引数にする.同じクラス内の
静的メソッドを呼び出す際は,「メソッド名(引数1,引数2, .. , 引数n)」の
ように書く.
dx, dyはここで値を代入されるが,rを求めた後は参照されないので,この部 分だけで有効なローカル変数(local variable)にする.
変数rだけはこの部分を実行後にも値を使いたいので,return 文によって,値 を返す.返したい値の型は,doubleなのでメソッドの返り値の型も doubleに なる.
| 上で述べたように,メソッドでは1つの値しか返すことができない.複数の値 を返したい時は,複数の値をまとめたようなクラスを作って,それを返すメソッ ドにする方法が一般的である. |
class Point2D {
public double x,y;
}
public class ObjectTest2 {
// Point2Dクラスの point1とpoint2の間の距離(2次元における)を返す
// 静的メソッド distance2Dの定義
public static double distance2D(Point2D point1,Point2D point2){
// point1, point2のx座標の差を dxに、y座標の差を dyに入れる
double dx=(point1.x-point2.x),dy=(point1.y-point2.y);
// dxとdyの2乗和の平方根を返す。
return Math.sqrt(dx*dx+dy*dy);
}
public static void main(String[] args){
Point2D p1,p2,p3;
// Point2Dクラスのインスタンスを作成し、p1に入れる。
p1=new Point2D();
p1.x=0.0;
p1.y=0.0;
p2=new Point2D();
p2.x=1.0;
p2.y=1.0;
p3=new Point2D();
p3.x=0.0;
p3.y=1.0;
// p1とp2の間の距離を表示する。
System.out.println("distance between p1 and p2 "+distance2D(p1,p2));
System.out.println("distance between p2 and p3 "+distance2D(p2,p3));
System.out.println("distance between p3 and p1 "+distance2D(p3,p1));
}
}
System.out.println("distance between p1 and p2 "+distance2D(p1,p2));
のようにおこなったが,静的メソッドは省略しないで書くと,
System.out.println("distance between p1 and p2 "+ObjectTest2.distance2D(p1,p2));
のように,「型名.メソッド名」という形をしている.よく使われるあるパター
ンをどのクラスの静的メソッドにするかというのは,プログラムの設計の問題
であり,難しい選択となることもあるが,上の例ではdistance2D という概念は
Point2Dというクラスに付随するものなので,Point2Dクラスの静的メソッドに
した方がよいだろう.そうすると,
class Point2D {
public double x,y;
// distance2Dという概念はPoint2Dクラスに付随すると考えられるので、
// Point2Dクラスの静的メソッドとして定義
public static double distance2D(Point2D point1,Point2D point2){
double dx=(point1.x-point2.x),dy=(point1.y-point2.y);
return Math.sqrt(dx*dx+dy*dy);
}
}
public class ObjectTest3 {
public static void main(String[] args){
Point2D p1,p2,p3;
p1=new Point2D();
p1.x=0.0;
p1.y=0.0;
p2=new Point2D();
p2.x=1.0;
p2.y=1.0;
p3=new Point2D();
p3.x=0.0;
p3.y=1.0;
// 静的メソッドの呼び出しは、「クラス名.メソッド名」でおこなう。
System.out.println("distance between p1 and p2 "+Point2D.distance2D(p1,p2));
System.out.println("distance between p2 and p3 "+Point2D.distance2D(p2,p3));
System.out.println("distance between p3 and p1 "+Point2D.distance2D(p3,p1));
}
}
となる.
class StTest{
public static void main(String[] args){
int i=100;
String s=String.valueOf(i);
System.out.println(s+s);
}
}
のように,intからStringに変換するのに使うメソッドだが,Stringのインス
タンスとは直接には結び付いていないメソッドなので,静的メソッドとなる.
実行例は以下のようになる.
dell.tanaka.ecc.u-tokyo.ac.jp% java StTest 100100
class Test11_3{
//
static void spaces(int l){
if(l==0) return;
System.out.print(" ");
spaces(l-1);
}
static void star(){
System.out.print("*");
}
public static void main(String[] argv){
int y;
for(y=0;y< 6;y=y+1){
spaces(y);
star();
spaces(10-y*2);
star();
System.out.println();
}
}
}
なお,メソッドspacesを再帰を使わずに書くと,
static void spaces(int l){
int i;
for(i=0;i< l;i++)
System.out.print(" ");
}
のように簡単に書ける.再帰を使ったものと対応が取れるように書き直すと,
static void spaces(int l){
for(;l >0;l--)
System.out.print(" ");
}
となる.上のようにfor文の初期化部分がない場合は何も入れなければ良い.
この例ではわざわざ再帰を使って書く必要はないが,再帰を使った方が自然に 分かりやすくかける場合も多い. 以下のプログラムは再帰を使って最大公約数を計算するプログラムである. なお このアルゴリズム(計算の方法)はユークリッドの互除法として良く知られてい る(GCDは Greatest Common Divisorの略).
class GCDTest {
// ユークリッドの互除法により最大公約数を計算するメソッド gcd の定義
// int型の引数 n, m をとり, int型の値を返す
static int gcd(int n,int m){
// デバッグ(プログラムのミスを直す)のための出力
System.out.println("gcd("+n+","+m+")が呼ばれました");
// 剰余を求めて rに入れる
int r=n%m;
// nがmの倍数になっているなら最大公約数は m自身になる.
if(r==0) return m;
// n,mの最大公約数は m,rの最大公約数と等しい
else return gcd(m,r);
}
public static void main(String[] args){
// コマンドラインから
// java GCDTest arg0 arg1
// のようにして起動した時, args[0] -> arg0, args[1] -> arg1 となる.
// 文字列から int 型の整数値に変換するのは Integer.parseInt を使う
int i0=Integer.parseInt(args[0]);
int i1=Integer.parseInt(args[1]);
System.out.println(i0+"と"+i1+"の最大公約数は"+gcd(i0,i1)+"です");
}
}
実行例は以下のようになる.
dell.tanaka.ecc.u-tokyo.ac.jp% java GCDTest 96 1024 gcd(1024,96)が呼ばれました gcd(96,64)が呼ばれました gcd(64,32)が呼ばれました 96と1024の最大公約数は32です
どうして, java クラス名とやると、そのクラスの public static void main(String[]) という型のメ ソッドから実行を始めるというようにしたのか、疑問を持つ人がいるのは当 然だろう。実際、C++ではクラスに属さない一般の関数 main で始まっている。Java言語では、プログラムの実行部分は全部メソッドでおこなわれ、すべて のメソッドをどこかのクラスに属するようにしたので、プログラム実行のスタ ート部分を特定のメソッド名に割り当てたということである.