5. Java言語プログラミング

今回より,Java言語を用いた数値計算プログラミングを行っていきます.EC科では,「インターネットプログラミング」の講義でJavaプログラミングを行いますが,復習の意味も含めてまずJavaの基礎について解説します.なお,ここでは,Javaのバージョンアップ等に伴う新機能などについては扱いません.

5.1 Javaとは?

5.2 Javaプログラミングの基礎

5.2.1 ソースファイルの作成,コンパイル,実行

5.2.2 プログラミングの基本事項

5.3 変数の宣言とデータ型,配列

5.3.1 変数の宣言とデータ型

5.3.2 配列

5.4 演算子

5.4.1 計算の演算子

5.4.2 比較演算子

5.4.3 論理演算子

5.5 プログラムの制御

5.5.1 判断・分岐

5.5.2 繰り返し

5.6 クラスとオブジェクト

5.6.1 クラスの定義

5.6.2 オブジェクトの生成

5.6.3 アクセス修飾子

5.6.4 フィールドの定義

5.6.5 メソッドの定義

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

5.6.7 コンストラクタ

5.6.8 クラスの継承

5.1 Javaとは?

Java言語は,Sun Microsystem株式会社(2010年1月にOracleの買収により完全子会社化)によって1995年に発表されたプログラミング言語です.もともとは,1991年に開発され,社内で内部的に使われていたOakと呼ばれる,家電製品に組み込むソフトウエア開発のために開発された言語でした.当初,Sun社は開発言語としてC++を考えていましたが,C++の仕様が冗長であることなどから採用せず,また,社内の様々な種類のコンピュータ環境で使用できるプログラムを作りたいという要望から,プラットフォームに依存しないプログラミング言語としてOakが開発されました.1995年,OakはJavaに改名され,インターネット上でJavaの開発環境である JDK (Java Development Kit) が無料でリリースされると,瞬く間に広まりました.

Javaが広まった大きな特徴として,いくつかの点があげられます.

(1) C言語やC++言語に似た表記方法

すでに広く利用されていたC言語やC++言語に似た表記方法を用いながら,それらの(ある面から見た)欠点をなくす設計となっています.例えば,CやC++のポインタは計算機のメモリを操作できる非常に有用な仕組みですが,使い方を誤るとシステムにダメージを与える可能性があります.

一方,Javaにはポインタや構造体などはなくメモリは全てJavaプログラム側で管理するため,開発者はメモリの確保や破棄などを考える必要がありません.また,後述のオブジェクト指向をサポートしている点や,プラットフォームに依存しない実行形態などもCやC++の(ある面での)欠点をなくしたものです.

(2) オブジェクト指向(Object-Oriented Programming: OOP)

例えば,C言語では,構造化設計をすることでプログラムを機能面から切り分けて管理することができますが,各機能は相互に依存するため,長大なプログラムを作る際には開発者は全てのプログラムの中身を把握している必要があり,プログラムの規模が大きくなるほどそれは困難になります.また,プログラムで使用するデータ(変数)とデータ処理機能(関数)を個別に考えるため,機能に適さないデータを誤って処理してしまう可能性もあります.

オブジェクト指向設計は,データ(変数)とデータ処理機能(メソッド)をひとまとめとして扱います.簡単に概念化できる「データ(もの)」と「データ処理機能(ものの振舞や扱い方)」をひとつのグループ(=クラス)とすることで,プログラムを分割・管理でき,グループ単位毎に内部の処理を設計し,グループの機能を利用する際にはグループ内の細かな処理を考える必要がありません.また,グループの中のデータにアクセスするためには必ずメソッドを使わなければならないため,データとデータ処理のミスマッチが起こりません(=カプセル化).

プログラムのコーディング方法が冗長であるC++に対し,Javaはオブジェクト指向に則ったプログラミングしかできません.


図5.1

(3) 実行ファイルレベルでのプラットフォーム非依存

CやC++では,あるプラットフォーム(計算機など)の基本ソフト(OSなど)上でコンパイルしたプログラムは,その上でしか動作しません.基本ソフトが異なるプラットフォームで実行するためには,またコンパイルしなおしたり,場合によってはソースプログラムを変更する必要があります.

Javaは,コンパイラとインタープリタを併用します.Javaのソースプログラムをコンパイルすると,バイトコードと呼ばれる実行プログラムの中間言語が生成されます.このバイトコードは JVM (Java Virtual Machine) と呼ばれるインタプリタがインストールされているプラットフォーム上であれば,どこでも実行できます.プログラムの実行環境自体を各プラットフォーム上に持たせることで,バイトコードを非常に小さくすることができ,これはネットワーク経由でプログラムをダウンロードして実行するなどの環境に適しています.

インタプリタは,命令を逐次解釈して実行するため速度が遅いという欠点がありますが,Javaではプログラムを高速に実行する仕組みを備えています.


図5.2

(4) ネットワーク親和性

Javaによって,webブラウザ上で実行する“アプレット”やwebサーバ上で実行する“サーブレット”など,ネットワーク上で実行可能なプログラムを開発できます.もともとJavaはこのようなネットワーク環境での利用が想定されています.JVMは,プログラムの実行状況を厳しく監視するセキュリティ機能が備わっており,疑わしい処理(ローカルファイルへの書き込みなど)が実行されそうな場合,その操作を防ぐことができます.また,前述のように,プログラムサイズが小さいためダウンロードに適していますし,プラットフォーム非依存のためネットワーク上の様々なプラットフォームでプログラムを実行することができます.

Java言語で作成できるプログラムには次のようなものがあります.この講義では,CUIアプリケーションを扱います.

・ CUI (Character User Interface) アプリケーション

コマンドプロンプトやShellなど文字ベースの実行環境 (CUI) で動作する基本的なプログラム.

・ GUI (Graphical User Interface) アプリケーション

ユーザとの情報のやりとりににグラフィックを用い、入出力操作のほとんどをマウスなどのポインティングデバイスによって行なう実行環境 (GUI) で動作するプログラム.

・ Javaアプレット

Webブラウザ上で動作するプログラム.Webサーバからプログラムがダウンロードされ,クライアント側のWebブラウザ上で動作する.

・ Javaサーブレット

Webサーバ上でJavaプログラムが動作し,その結果をWebページとしてクライアントに返す.

・ JSP (Java Server Page)

HTMLにJavaプログラムを埋め込んで,動的なWebページを作成するための仕組み.プログラムはWebサーバ上で実行され,その結果をクライアントに返す.

・ Java Beans

Java言語で作成したプログラムをコンポーネントとして扱うための仕組み.コンポーネントを組み合わせることで,アプリケーションを簡単に作成することが可能.

ページTOPへ

5.2 Javaプログラミングの基礎

5.2.1 ソースファイルの作成,コンパイル,実行

 

Eclipseなどの統合開発環境(Integratad Development Environment: IDE)を使う場合は,プログラムを作成・実行するための「プロジェクト」(関連するソースファイルやライブラリなどをまとめて管理して扱う単位)を作成し,IDE上のエディタでソースファイルを作成・編集し,実行します.操作手順は使用するIDEにより異なります.

IDEを使わない場合のプログラム作成・実行手順は,次のようになります.

(1) テキストエディタ(メモ帳,ワードパッド,Meadow,TeraPadなど)を使ってプログラムを記述し,ファイルを".java"という拡張子をつけて保存します.例えば,次のJavaプログラムを作成し,HelloWorld.javaというファイル名で保存します.このとき,class の後に続く名前とファイル名が一致している必要があります.

(プログラム: HelloWorld.java

      public class HelloWorld {

        public static void main(String[] args) {

          System.out.print("Hello ");
          System.out.print("world!\n");

          System.out.println("Hello world!");

        }

      }
    

(2) コマンドプロンプトを実行し,コマンドプロンプト上でソースファイルのあるディレクトリ(フォルダ)に移動します.例えば,C:(ローカルディスク)の中のworkディレクトリの下のprogrammingディレクトリの下にソースファイルHelloWorld.javaを保存した場合は,次のように移動します.

      C:\>cd \work\programming
    

(3) javac コンパイラにソースファイルを読ませ,コンパイルを実 行しバイトコードを作ります.

      C:\work\programming>javac HelloWorld.java
    

(4) コンパイルが正常に終了すると,同じフォルダ内に"HelloWorld.class" というバイトコードが作られます.ファイルはdirコマンドで確認できます.

(5) バイトコードを実行します.Java アプリケーションプログラムを実行するときは,JVMに実行するコードを渡すため,java コマンド + クラスファイル名(拡張子はいりません)と入力します.

      C:\work\programming>java HelloWorld
    

ページTOPへ

5.2.2 プログラミングの基本事項

Javaでは,プログラムの単位はクラスなので,必ず

      class クラス名 {
        …
      }
    

という記述でプログラムが始まり,{ }の間にこのクラスを定義する変数やメソッ ドを書きます.

ここでは,メソッドの例として,アプリケーションプログラムの実行単位であるmainメソッドを書きますが,プログラム自体はCやC++と同様に{ }で挟まれたブロックの間にメソッドの処理に必要な変数や式を書きます.式の最後にはセミコロン";"を書きます.

クラスやメソッドについては,もう少し後で説明します.

      class クラス名 {

        public static void main(String[] args) {

          変数;

          式;
          式;
      	  ・
      	  ・
      	  ・

        }
        
      }
    

CやC++と同様に,JAVAプログラムの記述はフリーフォーマットです.従って,プログラムを見やすくするために,コーディングの仕方に注意する必要があります(適切な改行,インデント,コメントの挿入など).

例えば,下の2つのプログラムは同じ動作をするものですが,二つめのプログラムのほうが内容や構造を理解できます.

public class HelloWorld { public static void main(String[] args) {System.out.print("Hello ");System.out.print("world!\n");System.out.println("Hello world!");}}

       * 20**/04/01
       * 基礎プログラミングおよび演習
       * Java サンプルプログラム
       * 文字列 "Hello World" を表示するクラス
       * T.Suzuki
       */

      public class HelloWorld {

        // main メソッド
        public static void main(String[] args) {

          // 文字列の表示
          System.out.print("Hello ");
          System.out.print("world!\n"); // \nは改行

          // 文字列の表示: printlnは改行付表示
          System.out.println("Hello world!");

        } // main メソッド

      } // class HelloWorld
    

演習5.1 (サンプルプログラム: NamePrintSample.java)

(解答例: NamePrint.java

次のように画面に表示するプログラムを作成し,コンパイル,実行しなさい.

大学名: 東京電機大学

学部名: 工学部

学科名: 情報通信工学科

氏 名: ○○○○(自分の氏名を入力)

ページTOPへ

5.3 変数の宣言とデータ型,配列

5.3.1 変数の宣言とデータ型

Javaで扱うデータは,型で分類されます.プログラム作成時には,扱うデータに応じて型を指定(宣 言)して使用します.

・ 整数型

byte: 1byte (= 8bit), -128~127

short: 2byte (= 16bit), -32,768~32767

int: 4byte (= 32bit), -2,147,483,648~2,147,483,647

long: 8byte (= 64bit), -9,223,372,036,854,775,808~9,223,372,036,854, 775,807

long型変数に整数を代入する場合は,数値の後に"l"または"L"を付ける.

long l = 1234567890l;

・ 実数型

flort: 4byte (= 32bit), ±3.4E+38~±1.4E-45

float型変数に十数値を代入する場合は,数値の後に"f"または"F"を付ける.

float f = 1.23f

double: 8byte (= 64bit), ±1.8E+308~±4.9E-324

実数型は,数値計算など実数を使用するような計算に用いられます.しかし,有効 桁数は有限のため,誤差に注意する必要があります.

・ 文字型,文字列クラス

char: 2byte (= 16bit)

一文字のみを記憶するデータ型です.プログラム中に文字データを書く場合は,'a' のようにシングルクォーテーションマークを使用します.

String:

文字列を格納するクラスです.プログラム中に文字データを書く場合は,"a"のよう にダブルクォーテーションマークを使用します.

・ 論理型

boolean

論理値trueまたはfalseを記憶するデータ型です.条件式や代入式などの真偽を判断 するときなどに使います.

変数の宣言と代入は,次のように行います.

      型 変数名1[, 変数名2,変数名3・・・];

      (例)  int i = 3;
            double x, y;
            char a = 'あ';
            String str = "あいうえお";

            x = 3.14;
            y = 2 * x;
            z = x + y;

            String text = str + i + "かきくけこ";
    

変数に数値を代入するには"="を使います.数学のイコール記号とは異なり,Java言語では代入を表し ます.右辺の値が左辺に代入されます.

      int a, b;
      char c1 = 'a';
      a = b = 10;
    

上の2行目では,文字型の変数c1にaという文字を代入しています.

3行目では,整数型の変数a, bに数値を代入していますが,この場合,まずbに10が代入され,次にb の値(=10)がaに代入されます.

型の異なる変数同士の計算や代入には,型変換(キャスト)を行います.キャストを用いないと,期待した演算結果が得られない場合があります.

      int a = 10;
      double b;

      b = (double)a;  // int型のaをdouble型にキャスト
    

変数名は,扱いたい変数あるいは値の,内容や役割を反映した英語名を付けます.自分のプログラムの見直しが容易になり,他の人からの可読性も高まります.


      int serverNumber = 10;
      double sensorValue;
      String localServerName = "labServ1";

    

演習5.2

(1) 摂氏Cを整数値で入力すると,実数値の華氏Fと絶対温度Kに換算し,それらを表示するプログラムを作成しなさい.

ただし,F = 32.0 + 1.8C,K = 273.16 + Cとする.

(サンプルプログラム: TemperatureConversionSample1.java

(解答例: TemperatureConversion1.java

(2) 上のプログラムの摂氏温度を,コマンドライン引数で入力するように改良しなさい.

(サンプルプログラム: TemperatureConversionSample2.java

(解答例: TemperatureConversion2.java

ページTOPへ

5.3.2 配列

配列により,同じ型の複数の変数をひとまとめに管理できます.関連した大量のデータを扱うときや,一連のデータを連続的に入出力するときなどは配列を使うと便利です.(参考: Java5以降では,保守性の高いコードを書くために,Collectionを使って配列の使用を減らすことが推奨されますが,ここではC言語やC++言語などに類似した配列表現を扱います.)

配列の宣言は,

      データ型[] 配列名;

      例)double[] a = new double[5];
    

のように行います.これは,例えば,double型の大きさの箱を5個用意し,それをaという名前でまとめて扱うという意味です.個々の箱は,それぞれa[0],a[1],・・・,a[4]として扱うことができます.配列数は,必ず 0 から数えます(配列数が5なら,配列は0~4).


図5.3

次の例は2次元の配列を宣言したものです.

      int[][] b = new int[2][3];
    

図5.4
 

3次元の配列の宣言は次のようになります.

      int[][][] c = new int[2][2][3];
    

図5.5

配列への数値の代入は,次のように行います.

      例)サンプルプログラム: ArrayPrintSample.java

      /*
       * 2011/06/03
       * 2011年度 基礎プログラミングおよび演習
       * Java サンプルプログラム (2)
       * 配列に値を代入し,表示するクラス
       * T.Suzuki
       */

      class ArrayPrintSample {

        // main メソッド
        public static void main(String[] args) { 

          // 配列の宣言
          double [] oneDimensionalArray = new double[3];
          int [][] twoDimensionalArray = new int[][]{ {1, 2, 3}, {4, 5, 6} };
          int [][][] threeDimensionalArray = { { { 7,  8,  9}, {10, 11, 12} },
                                               { {13, 14, 15}, {16, 17, 18} } };

          // 配列 oneDimensionalArray に値を代入
          oneDimensionalArray[0] = 1.2;
          oneDimensionalArray[1] = 3.45;
          oneDimensionalArray[2] = 6.789;

          // oneDimensionalArray[1]の値を表示
          System.out.print("1次元配列\n");
          System.out.println("配列の2番目の値 = " + oneDimensionalArray[1] + "\n");

          // 配列 twoDimensionalArray の値を表示

          System.out.print("2次元配列\n"); 

          for (int i=0; i<2; i++) {
            for (int j=0; j<3; j++) {

              System.out.print("[" + i + "][" + j + "] = " + twoDimensionalArray[i][j] + "\n");

            } 
          }
          System.out.print("\n");  // \n は改行

          // 配列 threeDimensionalArray の値を表示

          System.out.print("3次元配列\n"); 

          for (int i=0; i<2; i++) {
            for (int j=0; j<2; j++) {
              for (int k=0; k<3; k++) {

                System.out.print("[" + i + "][" + j + "][" + k + "] = " + threeDimensionalArray[i][j][k] + "\n");

              } 
            } 
          }
          System.out.print("\n");  // \n は改行

        }  // main メソッド

      }  // ArrayPrintSample クラス
    
  

演習5.3

上のサンプルプログラムをコンパイル,実行しなさい.また,代入値や次元数を変更し,配列の扱いについて理解を深めなさい.

演習5.4 (サンプルプログラム: ArraySortSample.java)(解答例: ArraySort.java, ArraySort2.java

5つの配列に自然数を入力し,昇順(小さい順)で配列の中身をソートし画面に表示するプログラムを作成せよ.

ヒント: 昇順ソートは次のバブルソートで行えます.

      int num = 5; //配列数
      int x[num]; //配列
      int i, k;
      int tmp;

          ・
          ・
          ・

      for (i=num-1; i>=1; i--) {
        for (k=0; k<i; k++) {
          if (x[k] > x[k+1]) {
            tmp = x[k];
            x[k] = x[k+1];
            x[k+1] = tmp;
          }
        }
      }
    

ページTOPへ

5.4 演算子

ここでは,計算や条件の比較などに使われる演算子をまとめておきます.

5.4.1 計算の演算子

演算子 使い方 意味
= a = b bの値をaに代入する
+ a = b + c bとcを足した値をaに代入する
- a = b - c bからcを引いた値をaに代入する
* a = b * c bとcをかけた値をaに代入する
/ a = b / c bをcで割った値をaに代入する
% a = b % c bをcで割った余りをaに代入する
+= a += b aにbを足した値をaに代入する
(a = a + b)
-= a -= b aからbを引いた値をaに代入する
(a = a - b)
*= a *= b aとbを掛けた値をaに代入する
(a = a * b)
/= a /= b aをbで割った値をaに代入する
(a = a / b)
%= a %= b aをbで割った余りをaに代入する
(a = a % b)
++ ++a
a++
aの値を1増やす.インクリメント演算子.
前置(++a)の場合は先に処理が行われ,
後置(a++)の場合は後で処理が行われる.
-- --a
a--
aの値を1減らす.デクリメント演算子.
前置(--a)の場合は,先に処理が行われ,
後置(a--)の場合は後で処理が行われる.

ページTOPへ

5.4.2 比較演算子

演算子 使い方 意味
== a == b aとbは等しい
< a < b aはbより小さい
> a > b aはbより大きい
<= a <= b aはb以下
>= a >= b aはb以上
!= a != b aとbは等しくない

ページTOPへ

5.4.3 論理演算子

演算子 使い方 意味
&& (0 < a) && (a <= 10) aが0より大きく,かつ,aが10以下
|| (a % 2 == 0) || (a % 3 == 0) aが2で割りきれる,または,aが3で割り切れる
! !(a == 10) aが10ではない.

ページTOPへ

5.5 プログラムの制御

if, switch, while, forの使い方を思い出してください.

5.5.1 判断・分岐

      if (条件式1) {

        条件式1が成立したときに実行される式;

      } else if (条件式2) {

        条件式2が成立したときに実行される式;

      } else {

        条件式1,2が成立しなかったときに実行される式;

      }
   
  
      switch (変数または式) {

        case 定数1:

          変数または式が,定数1の場合に実行される式;

        case 定数2:

          変数または式が,定数2の場合に実行される式;
            ・
            ・
            ・

        default:

          上記以外の場合に実行される式;

      }

    

ページTOPへ

5.5.2 繰り返し

      while (条件式) {

        条件式が成立している間だけ繰り返される式;

      }
    
      do {

        条件式が成立している間だけ繰り返される式;

      } while (条件式);  ←条件式の判定はループの最後
    
      for (初期設定; 反復条件; 変更式) {

        制御変数を初期設定から変更式で変更し,
          反復条件を満たしている間繰り返される式;

      }
    

演習5.5(サンプルプログラム: PrimePrintSample.java)(解答例: PrimePrint.java

二桁の素数をすべて出力するプログラムを適当な制御構文を用いて作成せよ.

ヒント: (エラトステネスの篩)

(1) 10~99までのすべての値を2, 3, 5, 7のいずれかで割り切れるかを判定する.

判定条件: x % 2 == 0 || x % 3 == 0 || x % 5 == 0 || x % 7 == 0

(2) 割り切れない場合は素数なので,その値を表示する.

演習5.6(サンプルプログラム: PrimeFactrizationSample.java)(解答例: PrimeFactorization.java

二桁の自然数(10~99)をコマンド引数として入力すると,素因数分解して出力するプログラムを適当な制御構文を用いて作成せよ.

ヒント: 素因数分解プログラムの流れ

(1) 入力値 x が,2, 3, 5, 7のいずれかで割り切れるかを判断.

条件: x % 2 == 0 || x % 3 == 0 || x % 5 == 0 || x % 7 == 0

(2) 割り切れない場合は x は素数.

(3) 割り切れる場合は,

・ まず,xが2より大きく,かつ,2で割り切れる間は文字"2 * "を表示し,xを2で割る.

・ 次に,xが3より大きく,かつ,3で割り切れる間は文字"3 * "を表示し,xを3で割る.

・ 次に,xが5より大きく,かつ,5で割り切れる間は文字"5 * "を表示し,xを5で割る.

・ 次に,xが7より大きく,かつ,7で割り切れる間は文字"7 * "を表示し,x を7で割る.

・ 最後に残った数 x を表示する.

ページTOPへ

5.6 クラスとオブジェクト

これから,実際にクラスを説明するためにプログラムを作っていきましょう.簡単な例として,次のような足し算を行うクラス Addition と,このクラスを利用して計算するメインメソッドを持つ Calculation クラスを考えていきます.なお,これらはクラスの記述について説明するためのプログラムですので,プログラムの中身についてはあまり気にしないでください.

      // リスト 1
      // 足し算クラス
      // ファイル: Addition.java

      // Addition クラス
      public class Addition {

        // (1)フィールドの定義
        private int num1;  // 同じクラス(Additionクラス)内のみアクセス可
        private int num2;  // 同じクラス(Additionクラス)内のみアクセス可
        public int ans = 0;  // どのクラスからもアクセス可

        // (2)メソッドの定義
        // 変数代入メソッド
        private void substituteValue(int a, int b) {
          // (3)同じオブジェクト内のフィールドへの代入
          num1 = a;
          num2 = b;
        }

        // 足し算メソッド
        public int addParameter(int a, int b) {
          // (4)同じオブジェクト内のメソッドの呼び出し
          substituteValue(a, b);
          // (5)同じオブジェクト内のフィールドの参照・代入
          ans = num1 + num2;
          // 戻り値
          return ans;
        }

      }  // Addition クラス
    
      // リスト 2
      // 実行クラス
      // ファイル: Calculation.java

      // Calculation クラス
      public class Calculation {

        // メインメソッド
        public static void main(String [] args) {

          // 変数の定義
          int a = 5;
          int b = 10;
          int result;

          // (1)オブジェクトの生成
          Addition addition = new Addition();

          // (2)異なるオブジェクトのフィールドの参照
          System.out.println("additionオブジェクトのフィールド ans = " + addition.ans);

          // (3)異なるオブジェクトのフィールドへの代入
          addition.ans = 100;

          System.out.println("additionオブジェクトのフィールド ans = " + addition.ans);

          // メソッドの呼び出し
          // (4)異なるオブジェクトのメソッドの呼び出し
          result = addition.addParameter(a, b);

          System.out.println("additionオブジェクトのフィールド ans = " + addition.ans);  
          System.out.println("同じオブジェクトのフィールド result = " + result);  

          // (5)アクセス修飾子の確認
          //  System.out.println("additionオブジェクトのフィールド ans = " + addition.num1);

        }  // main メソッド

      }  // Calculation クラス
    

演習5.7

リスト1(Addition.java),リスト2(Calculation.java)を作成し,リスト2のプログラムを実行して動作を確認しなさい.

ページTOPへ

5.6.1 クラスの定義

オブジェクト指向プログラミングは,共通・関連するデータと処理方法をひとまとめにした“プログラムの部品”を作り,その部品を組み合わせることでプログラムを作成します.個々の部品の独立性を高め,部品間の相互依存性をなくすことで,プログラムのメンテナンス性と再利用性を向上させます.この部品のことをクラスといいます.Javaでは,クラスのデータのことをフィールド,処理方法のことをメソッドと呼びます.フィールドやメソッドをまとめてクラスのメンバと言います.

クラス名は,クラスの役割や機能を表す名前を英語名で付けます.単なる番号や内容を想像できないような名前などは使わないでください.また,クラス名は,"JavaSampleClass" のように各単語の先頭を大文字にすることが一般的です.

ページTOPへ

5.6.2 オブジェクトの生成

クラスは,プログラムの部品を作るための設計図であり,それ自体は実体を持っていません.これは,変数の型と変数のようなもので,実際に利用するためにはクラスからオブジェクトを作ります.クラスからオブジェクトを作ることをインスタンス化と言います.

オブジェクトの生成は,リスト2 (1)のようにnew演算子を用いて行います.

      クラス名 オブジェクト名 = new コンストラクタ();
    

コンストラクタについては後で述べますので,ここではクラス名に()をつけたものと考えてください.

ページTOPへ

5.6.3 アクセス修飾子

publicprivateは,アクセス修飾子と呼ばれるもので,フィールドやメソッドのアクセス可能範囲を示します.publicとした場合は,すべてのクラスからアクセス可能,つまり,値を参照したり利用したりできます.privateとした場合は,そのメンバが記述されているクラスからのみアクセス可能で,他のクラスからはアクセスできません.

クラス,フィールド,メソッドなどは,アクセス範囲が分かるように,適切な修飾子を使って宣言してください.

ページTOPへ

5.6.4 フィールドの定義

フィールドはクラスの中で扱う変数であり,リスト1 (1)のように

変数の型 変数名;

で記述します.これをフィールドの定義といいます.同じオブジェクト内のフィールドは,リスト1 (3)のようにフィールド名をそのまま記述することで利用できます.異なるオブジェクトのフィールドは,リスト2 (2), (3)のように オブジェクト名+ピリオド+フィールド名 で記述します.

前述しましたが,変数名は,扱いたい変数あるいは値の,内容や役割を反映した英語名を付けます.

ページTOPへ

5.6.5 メソッドの定義

メソッドは,クラス内のデータの処理方法を与えます.メソッドの定義はリスト1 (2)のように

      戻り値の型 メソッド名(引数1,引数2,・・・) {

      }
    

とし,{ }で囲まれたブロックの中に処理内容の式を記述します.戻り値がない場合は,戻り値の型をvoidとします.引数がない場合は,メソッド名( ) のように,( )内にはなにも記述しません.

メソッド名は,そのメソッドがどのような処理を行うのかがわかるように,動詞で始まる英語名を付けてください.また,必要ならコメントなども付して何をするメソッドかを明確にしておきます.

同じオブジェクト内のメソッドの呼び出しはリスト1 (4)のように,メソッド名(引数)を記述します.異なるオブジェクトのメソッドの呼び出しはリスト2 (4)のように オブジェクト名+ピリオド+メソッド名(引数) と記述します.

いままで使ってきた main() もメソッドの一つで,プログラムを実行すると最初に呼び出されます.mainメソッドは,1つのクラスにひとつだけ記述でき,次のように書きます.

      public static void main(String [] args) {

      }
    

mainメソッドの引数はStringクラスの配列になっており,実行時のコマンドライン入力を受け取ります.例えば,リスト3のプログラムを実行するとき,次のように入力することでmainメソッドに引数を渡します.

      > java  Calculation  20  25

                          ↑ ↑

                       args[0]  args[1]

                      コマンドライン引数
    
      // リスト3 (リスト2変更)
      // 実行クラス
      // ファイル: Calculation.java

      // Calculation クラス
      public class Calculation {

        // メインメソッド
        public static void main(String [] args) {

          // 変数の定義
          int a = 5;
          int b = 10;
          int result;

          /*** リスト2に追加(ここから) ***/
          // コマンドライン引数の処理
          if (args.length != 2) {
            // (1)引数のString配列の要素数が2つではないときの処理
            System.out.println("2つの引数を入力してください(デフォルト値は5, 10です).");
          } else {
            // コマンドライン引数が入力されたときの処理
            // (2)文字列をint型に変換
            a = Integer.parseInt(args[0]);  
            b = Integer.parseInt(args[1]);
          }
          /*** リスト2に追加(ここまで) ***/

          // オブジェクトの生成
          Addition addition = new Addition();

          // メソッドの呼び出し
          result = addition.addParameter(a, b);

          // 結果の表示
          System.out.println("result = " + result);

        }  // メインメソッド

      }  // Calculationクラス
    

演習5.8

(1) リスト2 下から5行目のコメントアウトマーク(//)を消してコンパイルし,private修飾子のついたメンバには他のクラスからアクセスできないことを確認しなさい.次に,リスト1 9行目の変数(num1)の修飾子をpublicに変更し,リスト1,2ともそれぞれ再コンパイルした後にリスト2のプログラムを実行し,アクセス修飾子の意味を確認しなさい.

(2) リスト3で追加されている変更箇所をCalculation.javaに追加したのちコンパイルし,コマンドライン引数で値を入力して実行しなさい.

演習5.9(解答例: Subtraction.javaCalculation.java

リスト1のクラスを参考に,2つの整数の引き算を行い,結果を整数で返すメソッド subtractParameter をメンバに持つ引き算クラス Subtraction を作りなさい,また,Substractionクラスから引き算メソッドを呼び出し,結果を表示する命令をリスト3に追加しなさい.

ページTOPへ

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

オーバーロードとは,リスト4 (1), (2)のように,同じクラスの中に引数の型や数の異なる同じ名前のメソッドを複数定義することです.リスト5のように,引数の型と数に対応するメソッドが呼び出されます.

      // リスト 4
      // 四則演算クラス
      // ファイル: Addition2.java

      // Addision2クラス
      public class Addition2 {
        // フィールドの定義
        private int num1;
        private int num2;
        public int ans1 = 0;
        public double ans2 = 0.0;

        // メソッドの定義
        // 変数代入メソッド
        private void substituteValue(int a, int b) {
          // 同じオブジェクト内のフィールドへの代入
          num1 = a;
          num2 = b;
        }

        // 足し算メソッド(1): 引数は2つのint型
        public int addParameter(int a, int b) {
          // 同じオブジェクト内のメソッドの呼び出し
          substituteValue(a, b);
          // 同じオブジェクト内のフィールドの参照・代入
          ans1 = num1 + num2;
          // 戻り値
          return ans1;
        }

        // 足し算メソッド(2): 名称は(1)と同じで,引数の数が異なる(3つのint型)
        public int addParameter(int a, int b, int c) {  // メソッドのオーバーロード
          // 戻り値は,引数をすべて足した値
          ans1 = a + b + c;
          return ans1;
        }

        // 足し算メソッド(3): 名称は(1)と同じで,引数の型が異なる(2つのdouble型)
        public double addParameter(double a, double b) {  // メソッドのオーバーロード
          // 戻り値は,引数をすべて足した値
          ans2 = a + b;
          return ans2;
        }

      } // Addition2クラス
    
      // リスト 5
      // 実行クラス
      // ファイル: Calculation2.java

      // Calculation2クラス
      public class Calculation2 {

        // mainメソッド
        public static void main(String [] args) {

          // 変数の定義
          int a = 5;
          int b = 10;
          int c = 15;
          int result1;
          double f = 1.23;
          double g = 6.78;
          double result2;

          // コマンドライン引数の処理
          if (args.length != 2) {
            // (1)引数のString配列の要素数が2つではないときの処理
            System.out.println("2つの引数を入力してください(デフォルト値は5, 10です).");
          } else {
            // コマンドライン引数が入力されたときの処理
            // (2)文字列をint型に変換
            a = Integer.parseInt(args[0]);  
            b = Integer.parseInt(args[1]);
          }

          // オブジェクトの生成
          Addition2 addition2 = new Addition2();

          // メソッドの呼び出し.引数に対応したメソッド(1)が呼び出される.
          result1 = addition2.addParameter(a, b);
          // 結果の表示
          System.out.println("足し算メソッド(1): result = " + result1);       

          // メソッドの呼び出し.引数に対応したメソッド(2)が呼び出される.
          result1 = addition2.addParameter(a, b, c);
          // 結果の表示
          System.out.println("オーバーロードメソッド(2): result = " + result1);          

          // メソッドの呼び出し.引数に対応したメソッド(3)が呼び出される.
          result2 = addition2.addParameter(f, g);
          // 結果の表示
          System.out.println("オーバーロードメソッド(3): result = " + result2);  

        }  // mainメソッド

      }  // Calculation2クラス
    

演習5.10

リスト4,リスト5をそれぞれコンパイルした後,リスト5のプログラムを実行し,メソッドのオーバーロードについて確認しなさい.

演習5.11(解答例: Subtraction2.javaCalculation2.java

演習5.9で作成したクラスのメソッド subtractParameter を,2つの実数(double型)の引き算を行い結果を実数で返すようオーバーロードメソッドを追加しなさい.また,リスト5のクラスを参考に,引数の異なる引き算メソッドを呼び出し,結果を表示する命令をリスト5に追加しなさい.

ページTOPへ

5.6.7 コンストラクタ

コンストラクタは,オブジェクトを生成するときに呼び出される特殊なメソッドで,下のリスト6 (1)のようにクラスと同じ名前で戻り値がありません.コンストラクタは,主にオブジェクトの初期化などに使われます.また,リスト6 (2)のようにオーバーロードできます.

前述のリストのように,クラスの中にコンストラクタを記述しなくても,引数なしのコンストラクタが自動的に用意されます.これをデフォルトコンストラクタと言います.

      // リスト 6
      // 四則演算クラス
      // ファイル: Addition3.java

      // Addition3クラス
      public class Addition3 {

        // フィールドの定義
        private int num1;
        private int num2;
        public int ans1;
        public double ans2;

        // (1)コンストラクタの定義
        Addition3() {  // クラス名と同じ名前のメソッド
          // クラス内のフィールドの初期値の設定
          num1 = 0;
          num2 = 0;
          ans1 = 0;
          ans2 = 0.0;
        }

        // (2)コンストラクタのオーバーロード(引数が異なる)
        Addition3(int a, int b) {
          // クラス内のフィールドの初期値の設定
          num1 = a;
          num2 = b;
          ans1 = 0;
          ans2 = 0.0;
        }

        // メソッドの定義
        // 足し算メソッド(1): 引数なし.コンストラクタで初期化された値を使う.
        int addParameter() {
          // 同じオブジェクト内のフィールドの参照・代入
          ans1 = num1 + num2;
          // 戻り値
          return ans1;
        }

        // 足し算メソッド(2): 名称は(1)と同じで,引数の数が異なる(2つのint型)
        int addParameter(int a, int b) {  // メソッドのオーバーロード
          // 戻り値は,引数をすべて足した値
          ans1 = a + b;
          return ans1;
        }

        // 足し算メソッド(3): 名称は(1)と同じで,引数の数が異なる(3つのint型)
        int addParameter(int a, int b, int c) {  // メソッドのオーバーロード
          // 戻り値は,引数をすべて足した値
          ans1 = a + b + c;
          return ans1;
        }

        // 足し算メソッド(4): 名称は(1)と同じで,引数の型が異なる(2つのdouble型)
        double addParameter(double a, double b) {  // メソッドのオーバーロード
          // 戻り値は,引数をすべて足した値
          ans2 = a + b;
          return ans2;
        }

      }  // Addition3クラス
    
      // リスト 7
      // 実行クラス
      // ファイル: Calculation3.java

      // Calculation3クラス
      public class Calculation3 {

        // mainメソッド
        public static void main(String [] args) {

          // 変数の定義
          int a = 5;
          int b = 10;
          int c = 15;
          int result1;
          double f = 1.23;
          double g = 6.78;
          double result2;

          // コマンドライン引数の処理
          if (args.length != 2) {
            // (1)引数のString配列の要素数が2つではないときの処理
            System.out.println("2つの引数を入力してください(デフォルト値は5, 10です).");
          } else {
            // コマンドライン引数が入力されたときの処理
            // (2)文字列をint型に変換
            a = Integer.parseInt(args[0]);  
            b = Integer.parseInt(args[1]);
          }

          // (1)コンストラクタの呼び出しによるオブジェクトの生成
          Addition3 addition3 = new Addition3();
                  
          // メソッドの呼び出し
          result1 = addition3.addParameter();
          System.out.println("足し算メソッド(1)(値はコンストラクタで設定): result = " + result1);

          result1 = addition3.addParameter(a, b);
          System.out.println("足し算メソッド(1)(値はコマンドライン引数で設定): result = " + result1);

        }  // mainメソッド

      }  // Calculation3クラス
    

演習5.12

(1)リスト6,7をそれぞれコンパイルし,リスト7のプログラムを実行して,コンストラクタの動作を確かめなさい.

(2)リスト7において,addition3オブジェクトを作るコンストラクタを,

Addition3 addition3 = new Addition3(a, b);

に変更した後コンパイルし,プログラムを実行して動作の違いを確かめなさい.

演習5.13(解答例: Subtraction3.javaCalculation3.java

リスト6を参考に,Addition3クラスと同様の形でSubtractionクラスのコンストラクタを追加しなさい.また,リスト7にSubstractionオブジェクトを生成し,メソッドを呼び出す命令を追加して実行しなさい.

ページTOPへ

5.6.8 クラスの継承

オブジェクト指向プログラミングの大きな特徴のひとつとして,継承があります.継承とは,あるクラスのメンバを別のクラスで受け継いで利用するための仕組みで,元のクラスをスーパークラス(あるいは親クラス),受け継いだクラスをサブクラス(あるいは子クラス)といいます.サブクラスでは,スーパークラスのメンバを定義なしに使え,また,サブクラスで定義したメンバは当然使えます.ただし,スーパークラスのプライベート変数は,サブクラスでは使えません.


図5.6

また,リスト8 (4)のように,スーパークラスのメソッドをサブクラスで定義しなおすこともできます.これをメソッドのオーバーライドと言います.ただし,メソッドのオーバーロードと異なり,メソッドの引数と戻り値は同じでなければなりません

クラスを継承してサブクラスを作成するには,次のようにextendsを使います.

      // リスト 8
      // 掛け算クラス
      // ファイル: Multiplication.java

      // (1)Addition3クラスを継承したMultiplicationクラス
      public class Multiplication extends Addition3 {

        // フィールドの定義
        public int ans;

        //コンストラクタの定義
        Multiplication() {
          ans = 0;
        }

        // (2)新たなメソッドの定義
        public int multiplyParameter(int a, int b) {  

          // a×bの計算
          for (int i=0; i<b; i++) {
            // (3)スーパークラスのメソッドは,そのまま呼び出せる.
            ans = addParameter(ans, a);  
          }

          return ans;

        }

        // (4)メソッドのオーバーライド.引数と戻り値はスーパークラスと同じ.
        int addParameter(int a, int b, int c) {
         // メソッドの内容を変更
          System.out.println("メソッドがオーバーライドされました");
          return a + b + c;
        }

      }  // Multiplicationクラス
    
      // リスト 9
      // 実行クラス
      // ファイル: Calculation4.java

      // Calculation4クラス
      public class Calculation4 {

        // mainメソッド
        public static void main(String [] args) {

          // 変数の定義
          int a = 5;
          int b = 10;
          int c = 15;
          int result1;
          double f = 1.23;
          double g = 6.78;
          double result2;

          // コマンドライン引数の処理
          if (args.length != 2) {
            // (1)引数のString配列の要素数が2つではないときの処理
            System.out.println("2つの引数を入力してください(デフォルト値は5, 10です).");
          } else {
            // コマンドライン引数が入力されたときの処理
            // (2)文字列をint型に変換
            a = Integer.parseInt(args[0]);  
            b = Integer.parseInt(args[1]);
          }

          // オブジェクトの生成
          Multiplication multiplication = new Multiplication();

          // (1)スーパークラスの足し算メソッドの呼び出し
          result1 = multiplication.addParameter(a, b);
          System.out.println("スーパークラスの足し算メソッド: result = " + result1);

          // (2)サブクラスで定義した掛け算メソッドの呼び出し
          result1 = multiplication.multiplyParameter(a, b);
          System.out.println("サブクラスの掛け算メソッド: result = " + result1);       

          // (3)オーバーライドメソッドの呼び出し
          result1 = multiplication.addParameter(a, b, c);
          System.out.println("サブクラスで定義したオーバーライドメソッド: result = " + result1);       

        }  // mainメソッド

      }  // Calculation4クラス
    

演習5.14

リスト8,9をそれぞれコンパイルし,リスト9のプログラムを実行して,クラスの継承によるメソッドの動作を確かめなさい.

演習5.15(解答例: Division.javaCalculation4.java

リスト8,9を参考に,Subtractionクラスを継承して割り算を行うサブクラスDivisionを作りなさい.また,スーパークラスであるSubtractionクラスのsubtractメソッドを使って,2つの整数の割り算を行い結果を整数で返すメソッドdivideを作りなさい.リスト9のクラスに,Divisionクラスのメソッドを呼び出す命令を追加し,動作を確かめなさい.

演習5.16(解答例: PersonInfo.javaPersonInfoViewer.java

次の条件を満たす2つのクラスを作成し,動作を確認しなさい.

【PersonInfoクラス】

<フィールドの定義>

・名を代入するStringクラスのprivate変数.

・姓を代入するStringクラスのprivate変数.

・誕生年を代入するint型のprivate変数.

・誕生月を代入するint型のprivate変数.

・誕生日を代入するint型のprivate変数.

・年齢を代入するint型のprivate変数.

・所属を代入するStringクラスのprivate変数.

<コンストラクタの定義>

・引数のないデフォルトコンストラクタとして,フィールドの各変数に自分の情報を代入するコンストラクタを作る.

 ただし,ageについては,次のカレンダークラスを用いて,誕生年との差を代入すること.

      import java.util.GregorianCalendar;
      import static java.util.GregorianCalendar.*;

      class クラス名 () {

        // フィールドの定義

        // カレンダーオブジェクトの生成
        GregorianCalendar today = new GregorianCalendar();

        コンストラクタ() {
          代入式;
          ・・・
          年齢 = today.get(YEAR) - 誕生年;
          ・・・
        }

        コンストラクタ(引数) {
          代入式;
          ・・・
        }

        // メソッドの定義

      }
      

・各フィールドに入力する値を引数としてオーバーロードしたコンストラクタを作る.

<メソッド>

フィールドの情報を表示する.

【PersonInfoViewerクラス】

<mainメソッド>

PersonInfoクラスのメソッドを用いて,情報を表示する.

演習5.17(解答例: MyInfo.javaMyInfoViewer.java

次の条件を満たすクラスを作成し,動作を確認しなさい.

【MyInfoクラス】

<継承>

PersonInfoクラスを継承する.

<フィールド>

・自分の好みや趣味などを代入するStringクラスのプライベート変数を定義.

<メソッド>

・スーパークラスの情報に加えて,サブクラスで追加した情報を表示する.

<MyInfoViewerクラス>

・MyInfoクラスのメソッドを用いて,情報を表示する.

ページTOPへ