課題:講義資料オブジェクト指向プログラムJavaI&IIの中のサンプルプログラムについて考察せよ。
    *講義資料サンプルプログラム考察については、ローカル変数以降interface までとする。 

  名  前 仲松義嗣
 学籍番号 035735k
 所  属  工学部情報工学科
 提出期限 2003/12/15

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

・2つの変数の和と差の積を表示するプログラム

01:class Display { 02: int x,y; //クラス変数 03: void display() { 04: int i = x + y; //ローカル変数 05: int j = x - y; //ローカル変数 06: System.out.println(x*y); 07: } 08:} 09: 10:class Scope { 11: public static void main(String args[]) { 12: Display obj = new Display(); 13: obj.x = 10; //クラス変数にアクセス 14: obj.y = 2; //クラス変数にアクセス 15: //System.out.println(obj.i); //ローカル変数にアクセス 16: obj.display(); 17: } 18:}

実行結果1(15: //System.out.println(obj.i); ) j03035% javac Scope.java j03035% java Scope 96 実行結果2(15: System.out.println(obj.i); ) j03035% javac Scope.java Scope.java:15: cannot resolve symbol symbol : variable i location: class Display System.out.println(obj.i); ^ 1 error ---考察---  実行結果1と実行結果2よりあるクラスの変数に対するアクセスがその変数 をどこで宣言するかに依存することが分かります。そして、アクセス可能な変 数がクラス変数、不可能な変数がローカル変数と言われています。

static変数

・クラス変数を共有しないプログラム

01:class Conect { 02: String x; 03: Conect() { //コンストラクタ(クラス名と同名) 04: x = "Nakamatsu"; 05: } 06: void add(String y) { 07: x += y; 08: } 09:} 10: 11:class Static1 { 12: public static void main(String args[]) { 13: Conect obj1 = new Conect(); //クラスConectのオブジェクトobj1生成 14: Conect obj2 = new Conect(); //クラスConectのオブジェクトobj2生成 15: obj1.add("Yoshitsugu"); 16: obj2.add("kun"); 17: System.out.println("obj1.x = " + obj1.x); 18: System.out.println("obj2.x = " + obj2.x); 19: } 20:}

実行結果1 j03035% java Static1 obj1.x = NakamatsuYoshitsugu obj2.x = Nakamatsukun ・クラス変数を共有するプログラム

01:class Conect { 02: static String x; //static修飾子によるメモリ領域の共有 03: Conect() { //コンストラクタ(クラス名と同名) 04: x = "Nakamatsu"; 05: } 06: void add(String y) { 07: x += y; 08: } 09:} 10: 11:class Static2 { 12: public static void main(String args[]) { 13: Conect obj1 = new Conect(); //クラスConectのオブジェクトobj1生成 14: Conect obj2 = new Conect(); //クラスConectのオブジェクトobj2生成 15: obj1.add("Yoshitsugu"); 16: obj2.add("kun"); 17: System.out.println("obj1.x = " + obj1.x); 18: System.out.println("obj2.x = " + obj2.x); 19: } 20:}

実行結果2 j03035% java Static2 obj1.x = NakamatsuYoshitsugukun obj2.x = NakamatsuYoshitsugukun ---考察---  Static1の実行結果1とStatic2の実行結果2からクラス変数にstatic修飾子 を付けると、生成されたオブジェクト間でそのクラス変数が共有されることが 分かります。  ちなみに、ローカル変数にstatic変数を付けても、アクセスすらできないの で共有はもちろんできません。

コンストラクタ

・コンストラクタのオーバーロードプログラム

01:class Conect { 02: String x; 03: 04: Conect() { //コンストラクタ 引数無し 05: x = "Nakamatsu"; 06: } 07: Conect(String y) { //コンストラクタ 引数 y 08: x = y; 09: } 10: 11: void add(String z) { 12: x += z; 13: } 14:} 15: 16:class Constructer { 17: public static void main(String args[]) { 18: Conect obj1 = new Conect(); //クラスConectのオブジェクトobj1生成 19: obj1.add("Kun"); 20: System.out.println("Conect1 = " + obj1.x); 21: 22: Conect obj2 = new Conect("Yoshitsugu"); //クラスConectのオブジェクトobj2生成 23: obj2.add("Kun"); 24: System.out.println("Conect2 = " + obj2.x); 25: } 26:}

実行結果 j03035% java Constructer Conect1 = NakamatsuKun Conect2 = YoshitsuguKun ---考察---  クラス名と同じコンストラクタを違う引数で宣言すると、違うコンストラク タと認識されていることが分かります。  つまり、18:と22:のように違う引数でコンストラクタを宣言すると全く違う オブジェクトが生成されていると考えられます。

staticイニシャライズ

・staticイニシャライズのサンプルプログラム

01:class Calculater { 02: int x = 10; 03: int y = 5; 04: 05: static { //staticイニシャライズ 06: int x = 10; 07: int y = 5; 08: System.out.println(x + y); 09: } 10: Calculater() { //コンストラクタ 11: System.out.println(x - y); 12: } 13:} 14: 15:class StaticIn { 16: public static void main(String args[]) { 17: Calculater obj1 = new Calculater(); 18: } 19:}

実行結果 j03035% java StaticIn 15 5 ---考察---  mainメソッドの中では、10:で宣言したコンストラクタのオブジェクトを作っ ただけにもかかわらず、実行結果を視ると、staticの中のメソッドがコンスト ラクタよりも前に実行されていることが分かります。  つまり、static{}を使うことで、どのコンストラクタよりも早く処理したい メソッドを用意できそうです。

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

・メソッドのオーバーロードのサンプルプログラム

01:class Display { 02: void Disp() { //0個の引数を取るメソッドDisp 03: System.out.println("Nothing"); 04: } 05: void Disp(int x) { //1個の引数を取るメソッドDisp 06: System.out.println(x); 07: } 08: void Disp(int x, int y) { //2個の引数を取るメソッドDisp 09: System.out.println(x * y); 10: } 11: //int Disp(int x, int y) { //2個の引数を取るメソッドDisp 12: // return x % y; 13: //} 14:} 15: 16:class OverloadSample { 17: public static void main(String args[]) { 18: Display obj = new Display(); //クラスDisplayのオブジェクトobjの生成 19: 20: obj.Disp(); //オブジェクトobjのDisp()を実行 21: obj.Disp(1); //オブジェクトobjのDisp(1)を実行 22: obj.Disp(1,2); //オブジェクトobjのDisp(1,2)を実行 23: } 24:}

実行結果1 j03035% javac OverloadSample j03035% java OverloadSample 1 2 実行結果2 j03035% javac OverloadSample OverloadSample.java:11: Disp(int,int) is already defined in Display int Disp(int x, int y) { ^ 1 error ---考察---  実行結果2は11~13のコメントをはずしたものです。 実行結果1よりメソッドもコンストラクタと同様に引数の数や型を変えること で複数個の宣言が可能であることが分かります。 また、実行結果2より引数の数や型が同じで戻り値の違うメソッドを同時に 宣言することはできませんでした。  つまり、オーバーロードは戻り値には依存していません。

アクセス制御

01:class keisan { 02: static int tanka; 03: private float rate; //プライベート変数rate 04: 05: keisan() { 06: tanka = 1000; 07: rate = 0.05f; //同一クラスのメソッドからアクセス 08: } 09: 10: int keisan(int kazu) { 11: int kingaku; 12: 13: kingaku = (int)(tanka * kazu * (1.0 + rate)); //同一クラスのメソッドからアクセス 14: return kingaku; 15: } 16:} 17: 18:class PrivateSample { 19: public static void main(String args[]) { 20: keisan obj1 = new keisan(); 21: int kazu = 3; 22: int kingaku = obj1.keisan(kazu); 23: 24: System.out.println("tanka = " + obj1.tanka); 25: System.out.println("kazu = " + kazu); 26: System.out.println("kingaku = " + kingaku); 27: //System.out.println("rate = " + obj1.rate); //同一クラスでないクラスからのアクセス 28: } 29:}

実行結果 j03035% java PrivateSample tanka = 1000 kazu = 3 kingaku = 3150 ---考察---  27:のように同一クラスでないクラスからアクセスをしようとすると、コン パイルを通さないようです。

継承

・継承のサンプルプログラム

01:class Display { //スーパークラスDisplay 02: void Disp() { //スーパークラスのメソッドDisp 03: System.out.println("Happy?"); 04: } 05:} 06: 07:class Succeed extends Display { //スーパークラスDisplayを継承したサブクラスSucceed 08: public static void main(String args[]) { //サブクラスのmainメソッド 09: Succeed obj = new Succeed(); //オブジェクトの生成 10: obj.Disp(); //スーパークラスから継承したメソッドの利用 11: } 12:}

実行結果1 j03035% java Succeed Happy? ・複数のファイルを継承を利用してリンクさせるサンプルプログラム スーパークラス

01:class Display { //スーパークラスDisplay 02: void Disp() { //スーパークラスのメソッドDisp 03: System.out.println("Happy?"); 04: } 05:}

サブクラス

01:class Override extends Display { 02: void Disp() { //スーパークラスのメソッドDispをオーバーライド 03: System.out.println("Are you happy?"); 04: } 05: 06: public static void main(String args[]) { //サブクラスのmainメソッド 07: Override obj = new Override(); //オブジェクトの生成 08: obj.Disp(); //オーバーライドしたメソッドDispの実行 09: } 10:}

実行結果2 j03035% java Succeed Are you happy? ・オーバーライドの位置を確認するプログラム スーパークラス

01:class Display { //スーパークラスDisplay 02: void Disp() { //スーパークラスのメソッドDisp 03: System.out.println("Happy?"); 04: } 05:}

サブクラス

01:class Override extends Display { 02: public static void main(String args[]) { //サブクラスのmainメソッド 03: Override obj = new Override(); 04: obj.Disp(); 05: 06: void Disp() { //オーバーライドする位置の確認 07: System.out.println("Are you happy?"); 08: } 09: } 10:}

実行結果3 j03035% javac Override.java Override.java:6: illegal start of expression void Disp() { ^ Override.java:8: ';' expected } ^ 2 errors ---考察---  実行結果2より継承することでファイルをつなげることができることが分か ります。これにより、オブジェクト指向が高まり、再利用し易くなりそうです。  また、実行結果3よりオーバーライドの位置はmainメソッドの外である必要 がありそうです。

super

・スーパークラスのメソッドを呼び出す

01:class Display { 02: void Disp() { 03: System.out.println("Hello!"); 04: } 05:} 06: 07:class SuperSample extends Display { 08: void Disp() { 09: super.Disp(); 10: System.out.println("Hello! Java!!"); 11: } 12: public static void main(String args[]) { 13: SuperSample obj = new SuperSample(); 14: obj.Disp(); 15: } 16:}

実行結果1 j03035% java SuperSample Hello! Hello! Java!! ・スーパークラスのフィールドを呼び出す

01:class Display { 02: int i = 2; 03: void Disp() { 04: System.out.println(i); 05: } 06:} 07: 08:class SuperSample1 extends Display { 09: void Disp() { 10: super.i = 5; 11: System.out.println(i); 12: } 13: public static void main(String args[]) { 14: SuperSample obj = new SuperSample(); 15: obj.Disp(); 16: } 17:}

実行結果2 j03035% java SuperSample1 5 ---考察---  実行結果1と実行結果2よりスーパークラスのメソッドだけでなく、フィー ルドを呼び出すこともできることが分かります。

this

・カレントクラスのフィールドを呼び出す

01:class Keisan { 02: int x = 100; 03: void add(int x, int y) { //メソッドaddの生成 04: int w1 = x + y; 05: int w2 = this.x + y; //this.xがカレントクラスのx 06: System.out.println("w1 = " + w1 + " w2 = " + w2); 07: } 08:} 09: 10:class ThisSample1 { 11: public static void main(String args[]) { 12: Keisan obj = new ThisSample1(); 13: obj.add(10, 20); //メソッドaddの実行 14: } 15:}

実行結果1 j03035% java ThisSample1 w1 = 30 w2 = 120 ・カレントクラスのメソッドを呼び出す

01:class Keisan { 02: public Keisan(int x,int y) { //引数が2つのメソッド 03: System.out.println("Keisan = " + (x * y)); 04: } 05: public Keisan(int x) { //引数が1つのメソッド 06: this(x, 1); //カレントクラスのメソッドを利用 07: } 08:} 09: 10:class ThisSample2 { 11: public static void main(String args[]) { 12: Keisan obj1 = new Keisan(200,5); //引数が2つのメソッドを実行 13: Keisan obj2 = new Keisan(200); //引数が1つのメソッドを実行 14: } 15:}

実行結果2 j03035% java ThisSample2 Keisan = 1000 Keisan = 200 ---考察---  実行結果1は05:でカレントクラスのフィールドを呼び出しています。  実行結果2は06:でカレントクラスのメソッドを呼び出しています。

abstract

・抽象クラス

01:public abstract class PreDefine { 02: public abstract int add(int x,int y); //抽象メソッド 03: public int sub(int x,int y) { //メソッド 04: return x - y; 05: } 06:}

・抽象クラスを継承するクラス

01:class AbstractSample extends PreDefine { 02: public int add(int x, int y) { //抽象メソッドを実装 03: return x + y; 04: } 05: 06: public static void main(String args[]) { 07: AbstractSample obj = new AbstractSample(); 08: System.out.println("add = " + obj.add(100,80)); //抽象メソッドの実行 09: System.out.println("sub = " + obj.sub(100,80)); 10: } 11:}

実行結果 j03035% java AbstractSample add = 180 sub = 20 ---考察---  ファイルを区別することで開発を効率よく進めることができそうです。

interface

・インターフェイス

01:public interface PreDefine { 02: int add(int x,int y); //抽象メソッドadd 03: int sub(int x,int y); //抽象メソッドsub 04:}

・実行クラス

01:class InterfaceSample implements PreDefine { 02: public int add(int x,int y) { //抽象メソッドの実装 03: return x + y; 04: } 05: public int sub(int x,int y) { //抽象メソッドの実装 06: return x - y; 07: } 08: 09: public static void main(String args[]) { 10: InterfaceSample obj = new InterfaceSample(); 11: System.out.println("add = " + obj.add(100,80)); 12: System.out.println("sub = " + obj.sub(100,80)); 13: } 14:}

実行結果 j03035% java InterfaceSample add = 180 sub = 20 ---考察---  インタフェースは抽象クラスと違い、抽象メソッドのみからできています。 上のプログラムはインターフェイスに足し算をするaddメソッドと引き算をす るsubメソッドの抽象メソッドを定義しています。  実行クラス内で抽象クラスの実装をして、実行します。

感想・反省

  今回はHTMLの記述にもこだわってみました。
参考URL http://www.osnr.net/taniguchi/lecture/java/obj01.html
      http://www.osnr.net/taniguchi/lecture/java/obj02.html