課題
Report#5:講義資料オブジェクト指向プログラムJavaI&IIの中のサンプルプログラムについて考察せよ。



ローカル変数とクラス変数


プログラム例----------------------------------------------------------------

int n ;                                     // クラス変数
    void Disp() {
      int i;                                   // ローカル変数
      for (i = 1; i <= n; i++)
        System.out.print(i + " ");
    }
    
    void Disp2() {
      int i;                                   // ローカル変数
      for (i = 3; i <= n; i++)
        System.out.print(i + " ");
    }
}
  class VarSample {
    public static void main(String args[]) {
      Display obj = new Display();             // クラスDisplayのオブジェクトobj生成
      obj.n = 10;                              // オブジェクトobjの変数nに10を代入
      obj.Disp();                              // オブジェクトobjのDisp()実行
      obj.Disp2();                           //オブジェクトobjのDisp2()実行
    }
  }
  
実行結果----------------------------------------------------------------------
1 2 3 4 5 6 7 8 9 10 3 4 5 6 7 8 9 10 

考察

クラス変数?・・・・メソッドの外部で宣言した変数で各メソッドでも共通して使える。
ローカル変数・・・・メソッドの内部で宣言した変数。宣言したメソッド内でしか使えない。メソッドが呼び出されるたびに初期化される。
実行結果から初めDispメソッドが実行されて、次にDisp2メソッドが実行されている。

static変数


プログラム例------------------------------------------------------------------
class Sum {
    int total;
    Sum() {                              // コンストラクタ(クラス名と同名)
      total = 0;                         // 0 クリア
    }
    void add(int x) {
      total += x;
    }
  }
  
  class SumSample {
    public static void main(String args[]) {
      Sum obj1 = new Sum();              // クラスSumのオブジェクトobj1生成
      Sum obj2 = new Sum();              // クラスSumのオブジェクトobj2生成
      obj1.add(10);
      obj1.add(20);
      obj2.add(30);
      obj2.add(40);
      System.out.println("obj1.total = " + obj1.total);
      System.out.println("obj2.total = " + obj2.total);
    }
  }  

実行結果-----------------------------------------------------------------------
  obj1.total = 30
  obj2.total = 70

考察
obj1とobj2のtotalは別
staticを用いて値を共有するプログラム例-----------------------------------------

class Sum {
    static int total;                    // 値を共有させる
    Sum() {                              // コンストラクタ(クラス名と同名)
      total = 0;                         // 0 クリア
    }
    void add(int x) {
      total += x;
    }
  }
  
  class SumSample {
    public static void main(String args[]) {
      Sum obj1 = new Sum();              // クラスSumのオブジェクトobj1生成
      Sum obj2 = new Sum();              // クラスSumのオブジェクトobj2生成
      obj1.add(10);
      obj1.add(20);
      obj2.add(30);
      obj2.add(40);
      System.out.println("obj1.total = " + obj1.total);
      System.out.println("obj2.total = " + obj2.total);
    }
  }  

実行結果-----------------------------------------------------------------------
  obj1.total = 100
  obj2.total = 100
  

考察
static・・・・クラス変数、クラスメソッドにつける
クラス変数・・・・クラス全体で扱うデータを格納しておくフィールド。クラス変数は各オブジェクトから共有される。
2つのプログラムを比べると、はじめのプログラムはobj1とobj2の値が別だが、2つ目のプログラムはobj1とobj2の値が共有されている。

コンストラクタ


コンストラクタを用いた合計プログラム例 ----------------------------------------


  class Sum {
    int total;
    Sum() {                              // コンストラクタ 引数無し
      total = 0;
    }
    Sum(int x) {                         // コンストラクタ 引数 x
      total = x;
    }
    void add(int x) {
      total += x;
    }
  }
  
  class ConstrcSample {
    public static void main(String args[]) {
      Sum obj1 = new Sum();              // クラスSumのオブジェクトobj1生成
      obj1.add(10);
      obj1.add(20);
      System.out.println("sum1 = " + obj1.total);
      Sum obj2 = new Sum(100);           // クラスSumのオブジェクトobj2生成。引数100を代入
      obj2.add(10);
      obj2.add(20);
      System.out.println("sum2 = " + obj2.total);
    }
  }  

実行結果-----------------------------------------------------------------------
  sum1 = 30
  sum2 = 130

考察
コンストラクタ・・・・メソッドとたいへんよく似ているがコンストラクタの名前はクラス名と同じでなければならない。また戻り値は指定できない。そのクラスのオブジェクトが作成されたときに、定義しておいたコンストラクタ内の処理が自動的に行われる。

staticイニシャライズ

staticイニシャライズを行ったプログラム例---------------------------------------


  class Disp {
    static {                             // static イニシャライズ
        System.out.println("initialize");
    }
    Disp() {                             // コンストラクタ
        System.out.println("construct");
    }
  }
  
  class StaticSample {
    public static void main(String args[]) {
      Disp obj1 = new Disp();            // オブジェクト生成時にコンストラクタを処理
      Disp obj2 = new Disp();            // オブジェクト生成時にコンストラクタを処理
    }
  }  

実行結果-----------------------------------------------------------------------
  initialize     ※ Dispクラスのロード時に処理
  construct      ※ Disp.obj1 = new Disp(); が実行されるときに処理
  construct      ※ Disp.obj2 = new Disp(); が実行されるときに処理

考察
staticイニシャライズ・・・・クラスが呼ばれた時に1度だけ実行される。コンストラクタよりも早い。
実行結果よりobj1のコンストラクタよりも早く実行されている。また1度だけしか処理されないのでobj2のときは行われていないことが分かる。

メソッドのオーバーロード


メソッドのオーバーロードを行ったプログラム例-----------------------------------


  class Display {
    void Disp() {                          // メソッド Disp 引数なし
        System.out.println("Nothing");
    }
    void Disp(int x) {                     // メソッド Disp 引数 x
        System.out.println(x);
    }
    void Disp(int x, int y) {              // メソッド Disp 引数 x, y
        System.out.println(x + y);
    }
  }
  
  class OvldSample {
    public static void main(String args[]) {
      Display obj = new Display();    // クラスDisplayのオブジェクトobj生成
      obj.Disp();                     // オブジェクトobjのDisp()を実行
      obj.Disp(1);                    // オブジェクトobjのDisp(1)を実行
      obj.Disp(1, 2);                 // オブジェクトobjのDisp(1,2)を実行
    }
  }  

実行結果-----------------------------------------------------------------------
  Noting
  1
  3

考察
オーバーロード・・・・同じクラスの中に、同じ名前を持つメソッドを2つ以上定義することができる。ただし各メソッドの引数の型、個数が異なるようにしなければならない。
実行結果より、引数を入れずに実行すると引数を持たないメソッドが実行され、1つ入れると引数を1つ持つメソッドが実行され、2つ入れると引数を2つ持つメソッドが実行されている。

アクセス制御

privateを用いて、変数の参照を不可にするプログラム例----------------------------


  class keisan {
    static int tanka;
    private float rate;                    // private変数rateの宣言
    keisan() {                             // コンストラクタ
        tanka = 1000;
        rate  = 0.05f;
    }
    int keisan(int kazu) {
      int kingaku;
      kingaku = (int)(tanka * kazu * (1.0 + rate));
      return kingaku;
    }
  }
  
  class PrvSample {
    public static void main(String args[]) {
      keisan obj1 = new keisan();
      int kazu = 3;
      int kingaku = obj1.keisan(kazu);
      System.out.println("tanka   = " + obj1.tanka);
      System.out.println("kazu    = " + kazu);
      System.out.println("kingaku = " + kingaku);
  //  System.out.println("rate = " + obj1.rate);  //private変数のため参照不可
    }
  }  

実行結果-----------------------------------------------------------------------
  tanka   = 1000
  kazu    = 3
  kingaku = 3150


考察
private・・・・コンストラクタにつけるとクラスの外でそのコンストラクタが呼び出されるようなオブジェクトの作成ができなくなる。
プログラムの//(コメント)を外すとエラーが出ることから、privateをつけるとそのクラス外ではオブジェクトにしても使うことは出来ない。

継承

プログラム例-------------------------------------------------------------------

class Display {                                 // スーパークラス Display
    void Disp() {                               // メソッド
        System.out.println("Hello!");
    }
}

class Succeed extends Display {                 // スーパークラス Displayを継承したサブクラス Succeed
    public static void main(String args[]) {    // メソッド
        Succeed obj = new Succeed();            // オブジェクト生成
        obj.Disp();                             // スーパークラスから継承したメソッドを利用
    }
}

実行結果-----------------------------------------------------------------------
    Hello!

考察
継承・・・・新しく拡張したクラスが既存のクラスのメンバを受け継ぐことを言う。
既存のクラス・・・・スーパークラス
新しいクラス・・・・サブクラス
サブクラスの宣言方法・・・・class サブクラス extends スーパークラス 実行結果よりサブクラスのSucceedにはHelloは無いが、スーパークラスのDisplayから継承して表示している。
プログラム例-------------------------------------------------------------------


class Display {                                 // スーパークラス Display
    void Disp() {                               // メソッド
        System.out.println("Hello!");
    }
}

class Override extends Display {                // サブクラス Override
    void Disp() {                               // メソッドのオーバーライド
        System.out.println("Hello! Java!!");
    }
    public static void main(String args[]) {    // メソッド
        Override obj = new Override();          // オブジェクト生成
        obj.Disp();                             // メソッド Disp 実行
    }
}

実行結果-----------------------------------------------------------------------
    Hello! Java!!
	

考察
サブクラスOverrideにスーパークラスDisplayと同じメソッドDispをつくりオーバーライドすることができる。後で定義したほうが優先される。

super

プログラム例-------------------------------------------------------------------


class Display {                                 // スーパークラス Display
    void Disp() {                               // メソッド
        System.out.println("Hello!");
    }
}

class SuperSample extends Display {             // サブクラス SuperSample
    void Disp() {                               // メソッドのオーバーライド
        super.Disp();                           // スーパークラスの Disp 実行
        System.out.println("Hello! Java!!");
    }
    public static void main(String args[]) {    // メソッド
        SuperSample obj = new SuperSample();    // オブジェクト生成
        obj.Disp();                             // サブクラスの Disp 実行
    }
}

実行結果-----------------------------------------------------------------------
    Hello!
    Hello! Java!!

考察
super・・・・サブクラスでオーバーライトしたメソッドを呼び出すときに、オーバーライドされたスーパークラスのメソッドを呼び出す。

this

プログラム例-------------------------------------------------------------------


class Keisan {                                  // スーパークラス Keisan
    int x = 100;
    void add(int x, int y) {                    // メソッド
        int w1 = x + y;
        int w2 = this.x + y;
        System.out.println("w1 = " + w1 + "  w2 = " + w2);
    }
}

class ThisSample1 extends Display {             // サブクラス ThisSample1
    public static void main(String args[]) {    // メソッド
        ThisSample1 obj = new ThisSample1();    // オブジェクト生成
        obj.add(10, 20);                        // add 実行
    }
}

実行結果-----------------------------------------------------------------------
    w1 = 30  w2 = 120

考察
this・・・・このプログラムでthisはクラス変数と同じクラス内のメソッド変数が同じ名前のときにクラス変数につけて区別するために使われている。
thisを使わなかったらメソッド変数のxが使われていることがプログラムより分かる。
プログラム例-------------------------------------------------------------------
class Keisan {
    void Keisan(int x, int y) {                 // 引数が二つのコンストラクタ
        System.out.println("Keisan = " + (x * y));
    }
    void Keisan(int x) {                        // 引数が一つのコンストラクタ
        this(x, 1);                             // Keisan(x, 1)と同じ
    }
}

class ThisSample2 extends Display {             // サブクラス ThisSample2
    public static void main(String args[]) {    // メソッド
        Keisan obj1 = new Keisan(200, 5);       // 引数が二つのコンストラクタ実行
        Keisan obj2 = new Keisan(200);          // 引数が一つのコンストラクタ実行
    }
}

実行結果-----------------------------------------------------------------------
    Keisan = 1000
    Keisan = 200

考察
引数が2つと1つのコンストラクタをつくり、2つのコンストラクタには、クラス変数x,yをつくりx,yを足す。引数が1つのコンストラクタは、xをつくり計算は、引数が2つのコンストラクタのyに1を代入し、後は引数が2つのコンストラクタと同じ計算をする。

abstract


プログラム例-------------------------------------------------------------------


public abstract class PreDefine {               // 抽象クラス PreDefine
    public abstract int add(int x, int y);      // 抽象メソッド add
    public int sub(int x, int y) {              // メソッド sub
        return x - y;
    }
}

class AbstractSample extends PreDefine {        // 抽象クラス PreDefine の継承
    public int add(int x, int y) {              // メソッドの内容を具体的に定義
        return x + y;
    }

    public static void main(String args[]) {    // メソッド
        AbstractSample obj = new AbstractSample();
        System.out.println("add = " + obj.add(100, 80));
        System.out.println("sub = " + obj.sub(100, 80));
    }
}

実行結果-----------------------------------------------------------------------
    add = 180
    sub = 20

考察 abstract・・・・クラス、メソッド宣言時に付けて、抽象クラス、抽象メソッドを宣言する。抽象クラスはオブジェクト を生成することが出来ず、抽象メソッドと抽象メソッドでないメソッドを生成できる。
抽象メソッドは実装がなくサブクラスで継承して実装してオブジェクトを生成する形をとる。
プログラムのaddメソッドが抽象メソッドでAbstractSampleに継承して、抽象メソッドaddを実装し、AbstractSampleをオブジェクトにして実行している。

interface


プログラム例-------------------------------------------------------------------

public interface PreDefine {                    // インタフェース PreDefine
    int add(int x, int y);                      // 抽象メソッド add
    int sub(int x, int y);                      // 抽象メソッド sub
}

class InterfaceSample implement PreDefine {     // PreDefine のインプリメント
    public int add(int x, int y) {              // メソッドの内容を具体的に定義
        return x + y;
    }
    public int sub(int x, int y) {              // メソッドの内容を具体的に定義
        return x + y;
    }

    public static void main(String args[]) {    // メソッド
        InterfaceSample obj = new InterfaceSample();
        System.out.println("add = " + obj.add(100, 80));
        System.out.println("sub = " + obj.sub(100, 80));
    }
}

実行結果-----------------------------------------------------------------------
    add = 180
    sub = 20

考察
interface・・・・インターフェイスの宣言をする。インターフェイスとはabstractと似ているが、インターフェイスは抽象メソッドしか定義できない。また複数実装することができ、実装したクラスとの間にクラス関係を意識する必要が無い。

反省・感想
このレポートは英語のテストと重なりとても大変だった。内容もこれでいいのか自信がないがやっているところは理解できたと思う。
参考文献
やさしいjava
http://www2s.biglobe.ne.jp/~yuuki_ki/