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文の初期化部分がない場合は何も入れなければ良い.
この例ではわざわざ再帰を使って書く必要はないが,再帰を使った方が自然に 分かりやすくかける場合も多い.
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です
System.out.println("gcd("+n+","+m+")が呼ばれました");にあたる表示は残しても残さなくても良い.
dell.tanaka.ecc.u-tokyo.ac.jp% java GCDTest 96 1024 96と1024の最大公約数は32です 96と1024の最小公倍数は3072ですヒント
どうして, java クラス名とやると、そのクラスの public static void main(String[]) という型のメ ソッドから実行を始めるというようにしたのか、疑問を持つ人がいるのは当 然だろう。実際、C++ではクラスに属さない一般の関数 main で始まっている。Java言語では、プログラムの実行部分は全部メソッドでおこなわれ、すべて のメソッドをどこかのクラスに属するようにしたので、プログラム実行のスタ ート部分を特定のメソッド名に割り当てたということである.