横山実習室へ戻る

JAVA プログラムの読み方


 従来のプログラムでは、内容を理解する際、言語のもつ予約語をたよりに 解釈をすすめる傾向があり、それで十分であった。
 JAVAでの予約語は C とほとんど変わらないが、記述のほとんどは クラスの用語で記述されていて、言語の予約語では理解の糸口もつかめない。
 クラスの内容を知ることが大事であるが、多すぎてとても覚えられない状況 の中でJAVAプログラムを理解するには、まずコンパイラのように文の構造から 各要素が文法上の何であるかを解釈することから始めれば、全体の理解の糸口 になると考える。

C 言語との大きな違い
オブジェクト指向の言語であるために、クラスと呼ばれるまとまりを作らねばならない
以下にクラスの目的、特徴などをのべる。
・ クラスはc言語のSTRUCT、COBOLの集団項目などのようにデータ構造を定義するのが主たる目的と考えること。
・ クラスの中にはデータ領域の他にメソッドと呼ばれる関数を含めるが、クラスのデータを気軽に取り扱う(名前を書くだけでアクセスできる)ように するのがクラスに含めた目的と思えばよい。
・ クラスで定義するデータ構造はクラス名をデータ型と考えて、変数名を 変えて複数の領域に展開できるのが、c言語のSTRUCTと同様である。
これをインスタンスまたはオブジェクトの変数を作成すると言う。
・ 実際のデータ領域は new クラス名()で確保し、その復帰値が領域 のポインタ(Javaでは参照と呼ぶ)でこれを変数に代入する。
・ new クラス名()と書くと、クラス内のメソッドも含めて大きな領域 が取られないか、複数のメソッドができて混乱しないかと心配する必要は ない、メソッドは最初から領域を割り当てられており、この時点での領域 確保は、データ領域のみである。
以上、説明不足ではあるがクラスとは単にデータ領域確保の単位であると 簡単に考えて次に進むこと。
データ領域が必要無くても形式的にクラスにまとめることがオブジェクト指向の標準化だと思え。

1.クラス定義および骨格を見る

import パッケージ名
public class クラス名 extends クラス名 implements インターフェース名
{ //  クラス変数
public クラス名(){

// コンストラクタ
}
// メソッドの記述
public static void main( String[] args ){
クラス名 変数 = new クラス名();
}
}


 ① 継承( extends ) しているクラスは何か
   例 Applet を継承していれば メソッド paint が必須である

 ② インターフェース( implements )
例 イベント処理のインターフェースが記述されていれば、そのイベントに対応
     する 決められたメソッド が必須である。

 ③ クラス名と同一のメソッド名があればコンストラクタであり、オブジェクトが
   作られた時、最初に動作するメソッドである。

 ④ main メソッドがあれば、アプリケーションとして動作できる(デバッグ用の起動
   を含む)


2、クラス変数定義、メソッドの定義の見分け方

   識別子 型名 変数名,・・・ ;

識別子 型名 メソッド名( 型名 変数名,・・・ ){
// メソッドの定義
}
 
識別子は public , protected, private, 省略のどれかと static の組み合わせ

型名は int, boolean などの基本データ型 または クラス名

 ① クラス変数定義、メソッドの定義はどちらも識別子 型名 で始まる。
   たとえば public int ・・・ 、public Point ・・などの形式で、
   この部分ではクラス変数定義、メソッドの定義は区別できない。  

 ② つづいて、変数名、またはメソッド名がくるが、これも任意の文字列であり
   この部分ではクラス変数定義、メソッドの定義は区別できない。  

 ③ つづいて、(・・・){ が来ればメソッドの定義である。

 ④ 変数定義は 変数名; または 変数名= または []変数名 または 変数名[]

   の形式で括弧(・・・)が来ることはない。

 ⑤ ・・・は引数の定義で 型名 変数名 がカンマで区切って繰り返し定義される。



3.メソッドの定義、メソッドの呼び出しの見分けかた


識別子 型名 メソッド名( 型名 変数名,・・・ ){ // メソッドの定義

メソッド名( 変数名,・・・ ); // メソッドの呼び出し
  

 ① どちらも 名前(・・・・)の形をしているが、・・・・の部分が異なる。
また、メソッドの呼び出しの場合は 前に型名が来ないことで見分ける。
 
② メソッドの定義では、たとえば aaaa( int x, int y, Point z ) で各変数の型名
   が記述されている。

 ③ メソッドの呼び出しでは、たとえば aaaa( x, y, z ) のように型名はない。

 ④ メソッドの呼び出しの場合、どのクラスに属するメソッドかをみきわめること
   が重要である。前にドットによる修飾がない場合は、自分のクラス、または
   先祖のクラスのメソッドである。ドットによる修飾があればクラス名、または
   クラスのインスタンス名であり、そのクラスに属するメソッドである。

⑤ メソッドがどのクラスに属するメソッドかが、分からなくては何をするかを
   理解できない。 JDKのクラスでは同様の機能には同一のメソッド名を
   つけるのが普通であり、同じ機能でもどのインスタンス(オブジェクト)
   に作用するかが理解できないと、プログラムの意味はまったく分からない。


4. クラス名の見つけ方


 ① クラス定義は class の後に、継承するクラスは extends の後にくるので
   すぐにクラス名とわかる。

 ② クラスのインスタンスを作成する場合は new の後にクラス名がくるが、new
   の後には クラス名の他に 基本データ型がくる場合もあり紛らわしい。

   例  int[][] sss = new int[30][30]; // 配列の定義
Point ddd = new Point(); // クラス Pointのインスタンス

 ③ 型名としてクラス名がくる場合は、識別できる予約語がないので文の構成の中で、

   型名がくる場所を判断することによりクラス名を見つける。

   例 Frame fr = new Frame();
public int aabb( int x, hhh h ){ // hhh は引数の定義でありクラス名

 ④ キャスティングとしてクラス名を使用する場合も型名の一種である。

   例  Z z = (Z) xytoz( new Point(1,3) );
                 // Z はあるアプリケーションのクラス

 ⑤ static 宣言されているあるクラスのメソッドを使用する場合のクラス名

   例  int cc = gobas.abs( bb );

abs( bb )はメソッドの呼び出しと判断できる、その前にドット(.)があるので
   gobas は あるクラスのインスタンスか、static 宣言されているあるクラス
   のどちらかである。



5.ドット(.)で結合された文字列


 ① クラス変数名を参照する場合は一般的には kkk.hhh の形式である。

   kkk はクラスのインスタンス名(オブジェクト名ともいう)、自分のクラス変数

   this.hhh と書くが、普通は this. は省略して単に hhh と書く場合が多い。
super.hhh superは先祖(継承の元)を示す。   

   static 宣言されたクラス変数の場合、kkk はクラス名でもよい。

   例 Color.brue // クラス Color の中で static int brue と宣言されている場

      gobas.kkk.nnn // クラスgobas の中で static Kkk kkk = new Kkk();
// Kkk はクラス、kkk はそのインスタンス
             // nnn はクラス Kkk のクラス変数

 ② 呼び出しに使用するメソッド名の場合も、クラス変数名の場合とまったく同じであ
る。

   例 gobas.kkk.get(); // get() はクラス Kkk のメソッド

 ③ 内部クラスを他のクラスから使用する場合も、ドット(.)が使用される。
   クラス名.内部クラスで指定できる。
 

6.クラスのインスタンスと匿名クラスの見分け方


  new クラス名(); //クラスのインスタンス
new クラス名( 変数名,・・・ ) ; //クラスのインスタンス

new クラス名(){ //匿名クラス
}


 ① new がくれば、クラスのインスタンスか匿名クラスである。

 ② クラス名() の後に {  が来れば匿名クラスである。

 ③ 匿名クラスはクラスを定義すると同時に、そのクラスのインスタンスも生成するの

   new がついている。



7.入れ子構造


addMouseListener( new MouseAdapter(){
メソッドの定義
}


 ① addMouseListenerメソッドの呼び出しに引数として匿名クラスを入れ子にした例で
ある。 
  分解すると以下の形式でも書くことができる。
  
  クラスのインスタンス = new クラス名(){
メソッドの定義
}
  addMouseListener( クラスのインスタンス) ; 

 ② メソッドの呼び出し、クラスのインスタンス生成、匿名クラスは その呼び出しで

  要求される型の引数を括弧内に記述するが、この引数の所はその型を復帰値とする
  メソッドの呼び出し、クラスのインスタンス生成、匿名クラスを入れ子にして、変数

  定義しないで直接に値を引き渡すことができる。
  
 ③ 演算、判定に使用する変数も同様に、その型を復帰値とするメソッドの呼び出し、

  クラスのインスタンス生成、匿名クラスで入れ子に記述することができる。

 ④ この入れ子構造が、初心者が JAVA の理解を難しくする要因であるが、熟練者に

  とっては記述の量を少なくすると同時に、受け渡しの変数を定義しなくて良いので
  便利な機能として多用されることになり、書き手と読み手のギャップを広げている。



 ⑤ 初心者はこの記述方法に早く慣れて、熟練者のようにこの機能を使いこなしてほし
い。


 7 イベント処理の記述方法

   前に述べた、匿名クラスをしようしたイベント処理がもっとも簡単に誤りなく
   処理できる。

   クラス名 変数名 = new クラス名(・・・) ; // イベントが発生する部品 

変数名.addリスナー名( new アダプター名(){
void メソッド名( イベント名 変数名 ){
イベントの処理
}
   );

   ① リスナー名、アダプター名、メソッド名,イベント名 は以下のように規則的
に名前がつけられている

     例 ActionListener
ActionAdaptor // 実際にはActionListenerにはAdaptorがない
actionPerformed  
ActionEvent

      Adaptorがない場合はアダプター名のところはリスナー名を書く


8. 参照を引数として受け取り、クラス変数を更新するメソッド

C言語に慣れたひとは、構造体のポインタを受け取りその構造体の内容 を更新する関数を多く作成してきた。
 JAVAでも参照を引数として受け取り、同様のことができる。ただし参照 そのものは値渡しなので、書き換えても呼び出し元にもどらないので、 注意すること。
以下にこの関係で誤り易い例を示す。
呼び出しもと
  String pm="どうなるか";
test( pm ); //呼び出し
System.out.println("out="+pm);
メソッド
  void test( String pm ){
pm="こうなる";
}


String はクラスであり、pmは明らかに参照である。  でも test で参照の中を変えているのではなく、参照そのもの を更新しているので、呼び出し元にもどらない。


9 コンパイルエラー

① IOException シンボルが解釈できません。

Try{
.........
catch( IOException e ) {
.............
}

import を忘れていませんか。