Category: Java

4.クラスの基礎


4章 クラスの基礎
1.クラスとは
 クラスとは、プログラムをある実世界のモノとして考え、それに必要なデータと働き(メソッド)をひとまとめにしたものである。
 クラスは、「System」クラスと「String」クラスがある。Systemクラスはディスプレイに文字を表示させるための標準出力、標準エラー出力に表示させるために用いてきた。「String」クラスは、文字列を担うクラスである。そのでーた(クラス変数)として文字列そのものを持ち、メソッドとして検索したり、つなげたり、部分文字列を抽出したりといったメソッドが定義されている。
 このように、データとそれらを扱うメソッドを作成したクラスは、そのクラスの内部がどのようになっているのか知らなくても、部品のように使用することができる。つまり、SystemクラスやStringクラスの中身を知らなくても(ソースコードを見なくても)、そのクラスを使って、プログラムを作ることができる。さらに、その部品(クラス)は他のプログラムを作成するときにも使いまわしができる。
2.クラスの作成
 ここでは、Mypoingクラスを作ってみる。Mypointクラスは座標を担うクラスで、メンバー変数として、X座標とY座標を持つ。メソッドとしては、2点間の座標を求めるメソッドと、ディスプレイに表示するためにString型に変換するメソッドを持つ。
 クラスを作成する場合、基本的に1ファイルに1クラスでファイル名はクラス名と同じにする必要がある。
MyPoint.java

class MyPoint{
    double m_x;
    double m_y;

    // 文字列に変換する
    public String toString(){
         return "X:"+m_x+"  Y:"+m_y;
    }

    // 距離を計算する
    public double calcDistance(MyPoint pnt){
          // Mathクラスは数学関係を担うクラス
          // Math.pow累乗を計算するメソッド
          // Math.sqrtはルートを計算するメソッド
     return Math.sqrt(Math.pow((m_x – pnt.m_x), 2) + Math.pow((m_y – pnt.m_y), 2));
    }
}
 

Test.java

import  java.io.*;
   
class  Test{
    public static void main(String args[ ] ){
         int n;
         MyPoint pnt1 = new MyPoint( );                 // (1)
         MyPoint pnt2 = new MyPoint( );                 // (1)

         pnt1.m_x = 10;
         pnt1.m_y = 20;

         pnt2.m_x = 50;
         pnt2.m_y = -20;

    System.out.println("pnt1 " + pnt1.toString( ));
    System.out.println("pnt1 " + pnt1.toString( ));
    System.out.println("距離:" + pnt1.calcDistance(pnt2));
    }
}
 


C:\java>javac Test.java

C:\java>javac Test
pnt1 X:10.0   Y:20.0
pnt2 X:50.0   Y:-20.0

距離:56.568542494923804

C:\java>

 クラスを定義した(MyPoint.javaを作成しただけ)では、クラスを使えるようにはならない。
Test.javaのように「new」をしてはじめてクラスを使えるようになる。このnewをインスタンスを作るまたはオブジェクトを作ると言う。
newを何個も行うことで、インスタンスをたくさん作ることができる。これらのインスタンスは別のものであるが、変数の値もインスタンスが異なれば違う値を保持する。この場合、pnt1のメンバー変数のm_xとpnt2のm_xは違う値を保持している。それはこのためである。

      __pnt1__    __pnt2__   
    |_____m_x = 10  |    |   m_x = 50   |
       |     m_y = 20  |    |   m_y = -20 |
        ↑          ↑
        |          |
        |          |

両者は違うメモリーに格納される。このため、別のものとなる。

3.コンストラクタ
 クラスには、インスタンスが作られた時に一度だけ実行される「コンストラクタ」というものがある。一般にコンストラクタにはそのクラスインスタンスを初期化するために使用される。
MyPoint.java

class  MyPoint{
    double m_x;
    double m_y;

    // コンストラクタ
    public Mypoint( ){
         System.out.println("コンストラクタ1が呼ばれました");
         m_x = 10;
         m_y = 20;
   }

    // コンストラクタ2
    public Mypoint(double x, double y ){
         System.out.println("コンストラクタ2が呼ばれました");
         m_x = x;
         m_y = y;
   }
 
    // 文字列に変換する
    public double clacDistance(MyPoint pnt ){
       // Matchクラスは数字関係を担うクラス
       // Match.pow累乗を計算するメソッド
       // Match.sqrtはルートを計算するメソッド
       return Math.sqrt(Math.pow((m_x – pnt.m_x),2) + Math.pow((m_y – pnt.m_y), 2));
   }
}
 

Test.java

import  java.io.*;

    public static void main(String args[ ] ) {
    int n;
         MyPoint pnt1 = new MyPoint();
         MyPoint pnt2 = new MyPoint(50, -20);

//     pnt1.m_x = 10;
//     pnt1.m_y = 20;

//     pnt2.m_x = 50;
//     pnt2.m_y = -20;

         System.out.println("pnt1 " + pnt1.toString());
         System.out.println("pnt2 " + pnt2.toString());
         System.out.println("距離:" + pnt1.calcDistance(pnt2));
   }
}
 


C:\java>javac Test.java

C:\java>javac Test
コンストラクタ1が呼ばれました
コンストラクタ2が呼ばれました

pnt1 X:10.0   Y:20.0
pnt2 X:50.0   Y:-20.0
距離:56.5685424923804

C:\java>

 

3.配列


3章 配列
1.配列とは
 例えば100個のデータが合った場合、これを変数a1,a1,a3・・・a100と設定したのでは大変だから、メモリー上に100個の連続した領域を確保し、何件ものデータを総括的に扱うことのできる方法を配列という。
 配列の添え字は、0からはじまるプログラム言語と、1から始まるプログラムがある。Javaは0からはじまる。COBOLは1。Javaは、配列を入れるための変数を宣言し配列の領域を確保し、確保した領域を宣言した変数に入れるという操作をしなければならない。領域を確保する際はどのくらいの大きさの配列かを指定しなければならないが、配列を入れるための変数を宣言する際にはどのくらいの大きさかは宣言しなくても構わない。
2.配列の宣言と初期化
Javaでは、配列を使用する場合に配列の最後を越えてアクセスしていないかどうかをチェックしています。つまり10個の要素しかない配列の11番目にアクセスすることはできない。(例外をスローする)
import  java.io.*;

class Test{
    public static void main(String args[ ]){
        
int a[ ] ;
         a =
new int [10];

         // 要素数が10の配列の11番目にアクセスしようとした 
    
// 添え字が0から始まるので、11番目は10になる
    
System.out.println(a[10]);
     }
}

C:\java>javac Test.java                                       ← コンパイルは正常 

C:\java>java Test
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException at Test.main(Test.java:9)
                                                                       ↑ 実行時にエラーが出る
C:\java>

配列の領域を確保するのと同時に、初期化を行うこともできる。
  
int raikyaku[ ] = { 1,2,3,4,5 } ;

この場合、配列の大きさは、初期化の際の要素数になる。つまり、上記の例では要素数が5つの配列になる。

実際の配列領域を入れるための変数があるという事は、配列領域を別の変数に代入することもできる。
import java.io.*; 

class Test{
    
public static void main (String args[ ]){
         
int a[ ] = {  1,2,3,4,5 } ;
          int b[ ] ;

          b = a ;

          System.out.println(b[3]);

          a[3] = 100;

          System.out.println(b[3]);
    }
}

C:\java>javac Test.java

C:\java>java Test
4
100

C:\java>

Javaでは変数を用いて配列の領域確保を行うことができる。すなわち、動的に配列のサイズを変化させることができる。
import java.io.*;

class Test{
   
public static void main(String args[ ]) {
         int i = 200;
        
int a[ ] = new int [i];
   
}
}

3.配列の使用法 
 配列は添え字を用いることで、その要素の読み書きをする。添え字は変数であっても構わない。
 
「int型」の要素数10個の配列を作り、これに1から10の数字を代入する例
// 添え字に変数を使わない例
import  java.io.*;

class Test{
     
public static void main (String args[ ]) {
           int a[ ] = new int [10];

           a[0] = 1;
          
a[0] = 2;
          
a[0] = 3;
          
a[0] = 4;
          
a[0] = 5;
          
a[0] = 6;
          
a[0] = 7;
          
a[0] = 8;
          
a[0] = 9;
          
a[0] = 10;
     }
}

// 添え字に変数を使った例
import  java.io.*; 
 
class Test{ 
    public static void main(String args[ ]){
        int a[ ] = new int [10];
       int i;         // 添え字
 
   for( i = 0 ; i < 10 ; i++ )
           a[i] = i+1;
  }
}

  
[配列の変数.length]とすることで、配列の大きさを取得できる。
import  java.io.*; 
 
class Test{ 
    public static void main(String args[ ]) {
        int a[ ] = new int [10];
       int i;         // 添え字
 
   for( i = 0 ; i < a.length ; i++ )
           a[i] = i+1;
  }
}

  
配列のコピー
import  java.io.*; 
 
class Test{ 
    public static void main(String args[ ]){
        int a[ ] = { 5,4,3,2,1 };
        int b[ ] = { 1,2,3,4,5 };

         // 配列の表示
    showArray(a);
    showArray(b);

         // 配列のコピー
         // 配列aの10番目からa.length個(すべて)を配列bの0番目へとコピーする
    System.arraycopy(a, 0, b, 0, a.length); 
 
         // 配列の表示 
    showArray(a);
    showArray(b);
   }
 
   // 配列を表示するメソッド 
    public static void showArray(  int a[ ] ){
   
for( int i = 0 ; i < a.length ; i++ ) 
        System.out.print(i+":"+a[i]+"\t");
   System.out.println("");
   }
}

  

C:\java>javac Test.java

C:\java>java Test
0:5     1:4     2:3     3:2      4:1  ←コピー前のa
0:1     1:2     2:3     3:4      4:5 
←コピー前のb
0:5     1:4     2:3     3:2      4:1 
←コピー前のa
0:5     1:4     2:3     3:2      4:1 
←コピー前のb(コピーされている)

C:\java>

5.2次元配列と多次元配列
 2次元配列とは、配列の配列である。イメージ的には表。1次元配列と同様に、配列を入れるための変数を宣言し、配列領域を確保して変数に代入するとういう手続きが必要になる。
  int a[ ][ ];                           // 2次元配列をいれるための変数
  
a = new int[3][4];                // 3行4列の2次元配列領域を確保

  a[0][0] = 10;
  
a[0][1] = 20;
  
a[1][2] = 30;
  
a[2][3] = 40;

  int a[ ][ ] = new int[3][4];     // 変数宣言と領域確保を同時にしてもよい

  a[0][0] = 10;
  
a[0][1] = 20;
  
a[1][2] = 30;
  
a[2][3] = 40;
 

10 20 ? ?  
? ? 30 ?
? ? ? 40
    int a[ ][ ] = { { 0, 1, 2, 3 } , { 4, 5, 6, 7 } , { 8, 9, 10, 11 }  };
    int b[ ][ ] = { { 0            } , { 4, 5,       } , { 8, 9, 10, 11 }  };
    int c[ ][ ] = { { 0, 1, 2, 3 } , { 4, 5, 6, 7 } , {                  }  };
 
配列a(3行4列)   配列b(3行)   配列c(3行)  
0 1 2 3 0 X X X 0 1 2 3 X = 存在しない領域
4 5 6 7 4 5 X X 4 5 6 7
8 9 10 11 8 9 10 11 X X X X
 

2.制御文

2章 制御文
1.順次構造
 制御文とは、プログラムの流れを制御するもの。他の多くの言語と同様、上から下にプログラムは実行される。この流れを「順次構造」という。しかし、ある処理を繰り返したり、条件によって異なる処理をさせたい場合は、順次構造以外の流れが必要になる。
 
2.単一分岐
分岐の条件が一つだけの場合を単一分岐という。
変数nが0なら処理1を、
0以外なら処理2を実行する

        |
    /\ 
 /n=0 \___no__
 \     
/        |
    \
/           |
        | yes        |
 _______| _____  ______| _______
 |   処理1 _| |   処理2 _|
        |              |
        |←――― l
        |

  if(n==0) {
               処理1;
  }
  else{
                処理2;
  }

nがm以上なら処理1を、
未満なら処理2を実行する

       
    /\ 
 /n≧m \___no__
 \      /        |
    \/           |
        | yes        |
 _______| _____  ______| _______
 |   処理1 _| |   処理2 _|
        |              |
        |←――― l
        |

  if(n>=m) {
               処理1;
  }
  else{
                処理2;
  }

左記に同じ、
こういう書き方もある

       
    /\ 
 / n:0 \___<___
 \      /        |
    \/≧        |
        | yes        |
 _______| _____  ______| _______
 |   処理1 _| |   処理2 _|
        |              |
        |←――― l
        |

 
 
 
 
 
 
 

charの内容が'A'であれば処理1を実行し、それ以外ならば何もしない
       
    /\ 
  /
ch='A'\__no__
 \      /        |
    \/           |
        | yes        |
 _______| _____        |
 |   処理1 _|       |
        |              |
        |←――― l
        |

  if(ch=='A') {
               処理1;
  }
  else{
                処理2;
  }

どの処理の例もすべて、処理後合流していることが重要。多重分岐など含めて必ず合流しなくてはならない。 
import   java.io.*; 

class Test {
     public static void main (String args[ ]) {
          int n;
          n = readNumber( );
          if ( 10 <= N && n < 20 )
              System.out.println("10代");
     }

     // キーボードから数字を入力するメソッド
     public static int readNumber ( ) {
           byte b [ ] = new byte[100];

           try {
                   System.in.read(b);
                   return integer.parselnt((new String(b)).trim());
           } catch (Exception e) {
                  return 0;
           }
      }
}

「10代以上」という条件と「20代未満」という条件を「&&」で区切ることで、その両方を満たす場合に限り以下の文が実行される。
さらに、複数の条件のうちどれか一つでもみたされていれば実行させたい場合は、「&&」の代わりに、「 || 」で区切る。
また、条件が満たされない場合の処理がなければ、「else」文を省略することもできる。
 
3.多重分岐
多重分岐とは、単一分岐を組み合わせたもので、単一分岐の処理の中にまたは条件分岐を含むためのものである。

    |
    /\ 
  /
条件1\___yes
 \      /        |
    \/         /\ 
    |no    /
条件2 \__yes___
    |     \       /          |
    |            \/             |
 _______|______  ______| no___   ______|______ 
 |   処理1 _| |   処理2 _|  |___処理3_|
        |              |                 |
        |←――― l ―――――l       
        |

Javaでの表記
    
    
    
    

if(条件1) {
                 if(条件2) {
                               処理3;
             {
             else{
                               処理2;
             }
}
else {
              処理1;
}
 
下記の例はキーボードから数字を入力し、その数字が負数なら「負数」、0なら「0」、整数なら「整数」と表示する。2例とも同じ結果。
import  java.io.*;

class Test {
       public static void main (String args[]) {
            int n;
            n = readNumber() ;
            if  ( n < 0 ) {
                  System.out.println("負数") ;
            }
            else {
                    if ( n = = 0 ) {
                                System.out.println("0") ;
                    }
                    else {
                           System.out.println("正数") ;
                    }
             }
        }

       // キーボードから数字を入力するメソッド
       public static int readNumber ( ) {
             byte b [] = new byte [100];

             try {
                    System.in.read ( b ) ;
                    return Integer.parselnt ( ( new Stirng ( b ) ).trim ( ) ) ;
             } catch( Exception e) {
                         return 0 ;
             }
       }
}

import java.io.*;

class Test {
      public static void main(String args[]) {
            int n ;
            n = readNumber ( ) ;
            if  ( n < 0 ) {
                System.out.println("負数") ;
            }
           else if  ( n == 0 ) {
                System.out.println ( "0") ;          
            }
            else {
                   System.out.printin("正数") ;
            }
      }

      // キーボードから数字を入力するメソッド
   public static int readNumber ( ) {
               byte b [] = new byte[100] ;

      try {
             System.in.read (b) ;
             return Integer.parselnt ( ( new String ( b ) ).trim( ) ) ;
      } catch ( Exception e) {
             return 0
            }
      }
}

 

 
4.ケース構造
  3つ以上の異なった処理の中から、条件にあった処理を行うことを多方向分岐という。
例)char の内容が'A'だったらwに65を、'B'ならば66をそれ以外なら0を代入する。
        |
    /\ 
 /
char 
 \      /
    \/

       | "A"       __________________
        |――――|     65 → w  |―――l
       |
"B"      ___________________          |
        |――――|     66 → w  |―――|
       |
default  ___________________          |
        |――――|     0 → w    |―――|
                                                  |
       l―――――――――――――l
       |
switch(chara) {
     case'A' : w=65 : break ;
     case'B' : w=66 : break ;
     default :  w=0 :  break ;
}
        |
    /\ 
 /
char  \
 \      /
    \/
       | "A"       __________________
        |――――|     65 → w  |―――l

        |            |―――――――――l
       | "B"    ↓___________________         
        |――――|     66 → w   |―――l
        |          
   |―――――――――l
       | default ↓__________________          
        |――――|     0 → w    |―――l
                                                  |
       l―――――――――――――l
       |
switch(chara) {
     case'A' : w=65 :
     case'B' : w=66 :
     default :  w=0 :
}
 
5.反復構造(while)
 while文は、前判定型であり、繰り返し処理に入る前に繰り返し条件をチェックする。したがって条件によっては繰り返し処理を1度も実行しない場合もある。
  1から100までの合計を求めてみる。
import java.io.*;

class  Test {
    public static void main (String args[ ]) {
        int n. t;

        n = 1;
        t = 0;

        while (n <= 100) {
             t = t + 1;
             n = n + 1;
        }
        System.out.println("1から100までの合計は"+t+"です") ;
    }
}
         
 

while文ではwhileの後の括弧の中に条件式を記述し、その条件式が真になる間処理が繰り返される。もちろん、複数の条件式を「&&」「||」でつなげることもできる。 
 
6.反復構造(do) 
 do~while文は、後判定型であり、繰り返し処理を行った後に繰り返し条件をチェックする。
例)1~100までの合計を求めてみる。 
import java.io.*;

class Test {
      public static void main(String args[ ]) {
              int n. t;
 
              n = 1;
              t = 0;
 
              do { 
                      t = t + n;
                n = n + 1;
              } while(n <= 100);
              System.out.println("1から100までの合計は"+t+"です") ;

      }

  

 
7.反復構造(for) 
 for文は、前判定型であり、繰り返し処理に入る前に繰り返しチェックする。
for文は、while文に初期設定と、変化式を組み合わせたものです。これまでの例と同様に1~100までの合計を求めてみる。 
import java.io.*;

class Test {
     public static void main (String args[])
          int n. t;

          n =  1;                                                   // 初期設定
          t = 0;                                                   // 初期設定

          while(n <=100) {
                t = t + n;
                n = t + 1;      // 変化式
    }
         System.out.println("1~100までの合計は"+t+""です") ;
     }

}

 for文ではこれらを一緒に組み込む事ができる。
import java.io.*; 

class Test{
      public static void main(String args[]) {
             int n.t;

             for( n = 1.t = 0 : n <= 100 : n = n + 1) {
                    t = t + n;
             }
             System.out.println("1~100までの合計は"+t+"です") ;
       }

}

すなわち 
       for ( 初期設定 ; 条件式 ; 変化式 )
                             繰り返し処理
import java.io.*;

class Test {
      public static void main (String args[]) {
           int n. t;

           n = 1 ;
           t = 0 ;

          for( ; n <=100 : n = n + 1) {
               t = t + n :
          System.out.println("1~100までの合計は"+t+"です") ;
     }
}

import java.io.*;

class Test {
     public static void main(String args[]) {
           int n. t;

           n = 1;                                                       // 初期設定
           t = 0 ;                                                       // 初期設定

      for ( : n <= 100 ; n = n + 1)
                    t = t + n ;

           System.out.println("1~100までの合計は"+t+"です") ;
     }
}

 
8.補助制御文 
 実際のプログラムでは、反復処理中に処理から抜け出した方がプログラムがすっきり書ける場合も少なくない。
 break 「while」「for」 などの反復処理中に使用すると、強制的に反復処理を抜ける。
 continue 反復構造中に使用すると、反復処理が終了した事になる。条件が真ならば再度反復処理。
 return 関数から抜ける。
● キーボードから月(1~12)を入力し、その月の日数を表示するプログラム
import java.io.*;

class Test {
     public static void main (String args[]) {
          int month;
          System.out.print("月(1~12)を入力してください : ") ;
          month = readNumber( ) ;

          swtich (month) {
          case 1;
          case 3;
          case 5;
          case 7;
          case 8;
          case 10;
          case 12;
                System.out.println(month+"月は31日です") ;
                break ;
          case 2;
                System.out.println(month+"月は28日か29日です") ;
                break ;
          case 4;
          case 6;
          case 9;
          case 11;
                System.out.println(month+"月は30日です") ;
                break ;
          default ;
                System.out.println("1~12を入力してください") ;
          }
     }

     // キーボードから数字を入力するメソッド
     public static int readNumber( ) {
           byte b[] = new byte[100];

           try {
                   System.in.read(b) ;
                   return Integer.parselnt((new String(b)) . trim( )) ;
           } catch (Exception e) {
                   return 0 ;
           }
      }
}

 
11.多重ループの抜け方 
class Test{
     public static void main (String args[]) {
          boolean bContinue = true;
          for(  int i = 0 ; i < 10 && bContinue : i++ ) {
                 for( int  j = 0 : j < 10 && bContinue : i++ ) {
                      System.out.println("i =" + i + " j=" + j ) ;
                      if ( i == 5 && j == 5 ) {
                          bContinue = false ;
                          break ;
                      }
                 }
           }
      }
}
 
上記の例では処理が少ないからこれでもスッキリして見えるが、処理が複雑になると、上述のようにひとつめのfor文の条件にフラグ判定をいれるのではなく、入れ子になっているfor文が終わった場所にif文で更に条件分岐が必要になる場合もある。
class Test{c 
     public static void main (String args[]) {
          boolean bContinue = true;
          for ( int i = 0 ; i < 10 && bContinue ; i++  ) {
                for ( int j = 0 ; j < 10 ; j++ ) {
                      System.out.println("i=" + i + " j=" + j ) ;
                      if ( i == 5 && j == 5 ) {
                          bContinue = false;
                          break ;
                      }
                }
                if ( !bContinue )
                    break ;
           }
      }
}
これでもまだ余分な処理が書かれていないからいいが、これが実際にプログラムになると他にもいろいろ入ってくるからみにくい。
実はJavaではforやwhileといった反復構造のみにラベルを使用することができ、break文でどのループを抜け出すか指定ができる。
class Test{
     public static void main (String args[]) {
     LOOP1;
     for ( int i = 0 : i < 10 : i++  ) {
            for( int j = 0 : j < 10 : i++ ) {
                 System.out.println("i=" + i + " j=" + j ) ;
                 if ( i == 5 && j == 5 ) {
                      break LOOP1 ;
                 }
            }

         }
    }
}