メソッド5態



メソッドは

[修飾子]戻り値の型 メソッド名([引数]){
 処理
   計算(引数)
[return 戻り値]
}

で定義し

[インスタンス名orクラス名.]メソッド名([引数])

で実行する。


と説明される。( ここで[ ] は無くてもいいものを表す。)


確かにそれはそうなのだが、これだけでは説明しきれないのもまた事実だ(怒)。なにしろメソッドによって動作の仕方がかなり違うのだ!


1)通常のメソッド
 呼び出し時に与えられた引数を使って動作する。いわゆる普通のメソッド。呼び出せばすぐ処理が終わり、値を返してきてそれで終わり。


2)paint型のメソッド
  呼び出しは

paint()

  もしくは

repaint()

  で、引数を持たないのに

  定義ブロックでは

paint(Graphics g){
    処理
    g.Graphicsメソッド()
    (返り値なし)
}

と、どこからとも無くGraphics型の引数gが現れ、しかも定義ブロック内でそれを使用できる。このgはグラフィクスコンテキストと説明されるが大概の解説書ではそれ以上の解説はなく初心者にはサッパリ分からないシロモノ(怒)で不安極まりないんじゃコラ!


3)キャスト

(変換したい型)(変換対象の変数・クラス)

 これは「宣言」だからメソッドでは無いような気もするが、初心者からすると同じである。
 (int)というメソッド名でdouble型などの変数の型を変更するメソッドと考えられる。というかどうせそういう形式で処理してるんだろ。


4)ソケット受付

  ServerSocket ss = new ServerSocket(12345);
  System.out.println("preaccepted");
 Socket s = servSock.accept();//←ここでクライアント接続を待ちうけ、取得する。
  System.out.println("accepted");

 ポート番号12345のサーバーソケットに接続してきたソケットをsとして定義する命令だが、なんとクライアントが接続してくるまで永遠に待ち続ける。上記の場合コマンドプロンプトウインドウには

preaccepted

と表示されたきり先に進まない。(スレッドの流れで解釈すると、SocketクラスのインスタンスservSockのメソッドaccept()で無限ループを回しているので、処理の流れが戻ってこない、と思われる。)


 この動作ルールを知らないと、ここでプログラムが止まることが認知すらできないだろう。止まらない事を前提にプログラミングすれば、これまで必ず処理がすぐ帰ってくるメソッドばかり使っていた初心者は戸惑う。
 しかも複数クライアントを受付けるサーバーではこのメソッド呼び出しの外側で無限ループを回すものだから余計混乱する。(というか俺が混乱した。その結果、このメソッドに対して、”クライアントの接続があると突然その位置から新しいスレッドが立ち上がる”という印象を持っていた。)


5)ラインバッファメソッド
更に受信データを扱う時は

InputStreamReader isr = new 
                  InputStreamReader(s.getOutputStream(),true);
BufferReader in = new BufferReader(isr);

while(true){
  String str = in.readLine();
  System.out.println(str);
}

 こうするとクライアントからの通信文を受け付けた瞬間に一行づつ表示できるわけだが、またしても素人はここで戸惑う。


なんでwhileのそとでgetOutputStream()メソッドを一回しか使ってないのにwhile内部でinから永遠に通信文を受け取り可能なんじゃぁぁぁぁぁぁ!!!!?


 まあ、つまりgetOutputStream()でソケットから通信文を取り出す行為と、readLine()でstrに文字列を代入する行為の間にはデータ受け渡しの断絶があるはずなのになぜうまく行くのか?という疑問だ。
 実を言うと俺自身も正確には分かってないみたいだが、こういうことだろう。「ラッピング」と言う概念がモノを言うのだ。そして扱っている対象が基本型ではなくクラス型(参照型)であるのがミソ。


 ラッピングとは「オブジェクトを他のオブジェクトにくるんでしまうこと」とよく説明される。それだけ聞くと

こんな印象を受けるが、これでは説明が不充分だ。


 inの内部のisrの内部のsに変化(ここでは通信文の受信)があると「自動的に」getOutputStream()が作動し、isrへの引数として渡されisrがそれを処理したデータが更にinのデータとして渡される。つまり

このように「sにデータが入る→s.getOutputStream()がisrに代入される→isrがinに代入される」が自動で進行するのだろう。
while文では、このinが保持する既に加工済みのデータを読んでいるのだ。しかも読み出して空きが出来たらwhileが回るよりも早く次のデータを加工して提示していると思われる。


解説書はこういう解説をちゃんとやってもらいたい。動作イメージが掴めないと気持ち悪い!
いや、それよりもJavaの開発者は


こういう動作にちゃんと名前を付けろ!
この舌足らずどもがっ!!
名前が無いと存在を認識できないんだよ!


俺だったらそうだな・・・「ラッピングによる自動処理」もしくは「オートカスケード(多段)プロセス」とでも名づける!




 ※これ以外にも(初心者にとって)特殊な動きをするメソッドがあったら教えて下さい。