[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

情報処理技法(Javaプログラミング)I 第12回

目次
索引

レコードとしてのインスタンス

レコードとは

レコード record )とは、(関連性のある)いくつかのデータをひとまとめにしたものです。 次の図はレコードのイメージを表しています。

レコードのイメージ
レコードのイメージ

レコードの構成要素を フィールド field )とよびます。 また、レコード自身のデータ型を レコード型 record type )とよびます。

以前、データをまとめたものとして配列を取り上げました。 配列とレコードには次のような違いがあります。

レコード型を定義するには、データ型としての名前、フィールドの名前、およびそれぞれのフィールドのデータ型を決めなくてはいけません。 上記のイメージの場合は、データ型としての名前をTime, フィールドの名前を hour minute , フィールドのデータ型を整数型(int型)と決めます。

実は、Javaにはレコードやレコード型はありません。 しかし、 インスタンス instance )や クラス class )というものが、代わりの機能を持っています。 一般的な用語とJavaの用語の対応は次の通りです。

レコードに関する用語の対応
一般 Java
レコード インスタンス
フィールド インスタンス変数
レコード型 クラス

この授業では、インスタンス、フィールド、およびクラスという用語を用います。

ちなみに、プログラミング言語によっては、レコードのことを構造体とよびます。

インスタンスの使い方

レコードとしてのインスタンスを使うには、まず、クラスを定義します。 フィールドのデータ型が整数型(int型)なら、クラスの定義は次のようになります。

static class クラス名 {
    int フィールド名1;
    ...;
    int フィールド名n;
}

ここで、「 クラス名 」はクラスの名前、「 フィールド名 」はフィールドの名前です。

注意: Javaのクラスにはいくつか種類がありますが、ここで紹介したのは 静的内部クラス static inner class )とよばれるものです。 Javaには 内部クラス inner class )という仕組みがあり、その中で 静的 static )なものという意味です。

次のプログラムは、変数を宣言し、インスタンスを生成してその変数に格納し、インスタンスのフィールドにデータを格納し、その値を表示するものです。

TimeTest.java
class TimeTest { // クラスのテスト
    static class Time { // クラス名
        int hour; // フィールド名
        int minute; // フィールド名
    }
    public static void main (String[] args) {
        Time x; // 宣言
        x = new Time(); // 生成
        x.hour = 9; // hourフィールドに格納
        x.minute = 30; // minuteフィールドに格納
        System.out.println(x.hour + ":" + x.minute); // フィールドの値を出力
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'TimeTest'
9:30
PS ...\Desktop\java1>

変数に整数(int型)を格納するには、変数の宣言が必要でした。 変数にインスタンスを格納するにも、同様に変数の宣言が必要です。 これは次のように書きます。

クラス名 変数名;

今まで int と書いていた部分をクラス名に変えます。 7行目で、変数 x をTimeクラスと宣言します。

クラスのインスタンスは、明示的に生成してはじめて使えます。 インスタンスを生成するには、キーワード new を用います。 「 クラス名 」のインスタンスを生成して、「 変数名 」に格納するには、

変数名 = new クラス名();

と書きます。 8行目で、Timeクラスのインスタンスを生成して、変数 x に格納します。

なお、次のように書くと、変数の宣言とインスタンスの生成、そしてその変数への格納が同時に行えます。

クラス名 変数名 = new クラス名();

インスタンスのフィールドにデータを格納するには、次のような文を用います。

変数名.フィールド名 = ;

これで、「 変数名 」に格納されているインスタンスの「 フィールド名 」に、「 」の値が格納されます。 9行目で、インスタンス x hour フィールドに9が格納され、10行目で、 minute フィールドに30が格納されます。

インスタンスのフィールドに格納されたデータを取り出すには、式

変数名.フィールド名

を用います。 この式の値は、「 変数名 」に格納されているインスタンスの「 フィールド名 」に格納されているデータです。 11行目で、インスタンス x hour フィールドと minute フィールドからデータを取り出して、出力します。

コンストラクター

クラスのインスタンスを扱う場合、これまでは、インスタンスを生成してからフィールドに値を格納しました。 つまり、次のように書きました。

Time x = new Time();
x.hour = 9;
x.minute = 30;

配列では、初期化を使ってプログラムを短くしました。 インスタンスでも、 コンストラクター constructor )というものを用いると、初期化に相当することができます。 上記の例なら、次のように書けます。

Time x = new Time(9, 30);

もし、クラスが

static class クラス名 {
    int フィールド名1;
    ...;
    int フィールド名n;
}

と定義されていたら、次のように定義し直すと、コンストラクターが使えるようになります。

static class クラス名 {
    int フィールド名1;
    ...;
    int フィールド名n;
    クラス名 (int フィールド名1, ..., int フィールド名n) {
        this.フィールド名1 = フィールド名1;
        ...
        this.フィールド名n = フィールド名n;
    }
}

これで、式

new クラス名(引数1, ..., 引数n)

を呼び出すと、「 フィールド名 1 」に「 引数 1 」を格納し、…、「 フィールド名 n 」に「 引数 n 」を格納したインスタンスになります。

コンストラクターはメソッドに似ています。 どちらも、あらかじめ定義しておき、呼出しによってその機能が働きます。 メソッドとコンストラクターは以下の点が異なります。

次のプログラムでは、コンストラクターも定義したクラスTimeを定義しています。 5行目から8行目までが、コンストラクター定義です。 このコンストラクターは、第1引数を hour フィールドに格納し、第2引数を minute フィールドに格納します。 11行目で、このコンストラクターが呼び出され、 hour フィールドに9が格納され、 minute フィールドに30が格納されます。

TimeTest2.java
class TimeTest2 { // コンストラクターのテスト
    static class Time {
        int hour;
        int minute;
        Time (int hour, int minute) { // コンストラクター定義
            this.hour = hour;
            this.minute = minute;
        }
    }
    public static void main (String[] args) {
        Time x = new Time(9, 30); // コンストラクター呼出し
        System.out.println(x.hour + ":" + x.minute);
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'TimeTest2'
9:30
PS ...\Desktop\java1>

注意1: 上記のコンストラクターは、最も単純なものです。 一般的には、コンストラクターはより複雑なことが行えます。

注意2: 上記のようにコンストラクターを定義すると、 new Time() ではインスタンスが生成できなくなります。 実は、コンストラクターを定義しなければ引数なしのコンストラクターが自動的に用意され、コンストラクターを定義すると定義したものだけが使えるという規則になっています。 引数ありと引数なしの両方のコンストラクターを使うには、次のように両方定義します。

static class Time {
    int hour;
    int minute;
    Time () {
    }
    Time (int hour, int minute) {
        this.hour = hour;
        this.minute = minute;
    }
}

インスタンスの使用例

インスタンスの例として、以前考えた買い物の問題を再び取り上げます。

A子は店に行き、150円のペットボトルの紅茶を1本と120円の缶コーヒーを3本買いました。 A子はいくら支払わなければならないでしょうか。

SomeDrinks2.java
class SomeDrinks2 { // いくつかの飲み物2
    public static void main (String[] args) {
        int total, tea = 150, coffee = 120;
        total = tea + 3 * coffee;
        System.out.println(total);
    }
}

このプログラムでは、値段だけを変数に格納し、個数は変数に格納しませんでした。 インスタンスを利用すれば、値段と個数をまとめて格納できます。

以下のプログラムでは、買った物を格納するために、Buyというクラスを定義します。 price というフィールドには値段を格納し、 count というフィールドには個数を格納します。

そして、Buyクラスの変数 tea を宣言し、Buyクラスのインスタンスを生成して tea に格納します。 変数 coffee についても同様に宣言・生成します。 インスタンス tea にはペットボトルの紅茶の値段と個数を格納し、インスタンス coffee には缶コーヒーの値段と個数を格納します。 最後に、合計金額を計算します。

BuyMain.java
class BuyMain { // 買った物のメイン
    static class Buy { // 買った物
        int price; // 値段
        int count; // 個数
    }
    public static void main (String[] args) {
        int total;
        Buy tea = new Buy(); // 宣言と生成
        Buy coffee = new Buy(); // 宣言と生成
        tea.price = 150; // ペットボトルの紅茶の値段は150円
        tea.count = 1; // ペットボトルの紅茶の個数は1個
        coffee.price = 120; // 缶コーヒーの値段は120円
        coffee.count = 3; // 缶コーヒーの個数は3個
        total = tea.count * tea.price + coffee.count * coffee.price;
        System.out.println(total);
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'BuyMain'
510
PS ...\Desktop\java1>

続いて、コンストラクターを利用して、このプログラムを短くします。

以下のプログラムでも、クラスBuyを定義します。 このクラスのコンストラクターは、引数が値段、個数の順になるように定義します。

そして、コンストラクターを呼び出して、Buyクラスの変数 tea にペットボトルの紅茶の値段と個数を格納します。 同様に、Buyクラスの変数 coffee に缶コーヒーの値段と個数を格納します。 最後に、合計金額を計算します。

BuyMain2.java
class BuyMain2 { // 買った物のメイン2
    static class Buy {
        int price;
        int count;
        Buy (int price, int count) { // コンストラクター定義
            this.price = price;
            this.count = count;
        }
    }
    public static void main (String[] args) {
        int total;
        Buy tea = new Buy(150, 1); // コンストラクター呼出し
        Buy coffee = new Buy(120, 3); // コンストラクター呼出し
        total = tea.count * tea.price + coffee.count * coffee.price;
        System.out.println(total);
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'BuyMain2'
510
PS ...\Desktop\java1>

演習12

ある小学校で国語と算数の試験が行われました。 太郎君は国語が70点、算数が80点でした。 花子さんは国語が90点、算数が100点でした。 インスタンスを利用して、これらの得点データを格納し、全体の平均点(小数点以下切り捨て)を計算してください。

ScoreMain.java
class ScoreMain {
    static class Score {
        
        
    }
    public static void main (String[] args) {
        
        
        
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'ScoreMain'
85
PS ...\Desktop\java1>

まず、試験の得点を格納するするために、クラスScoreを定義します。 フィールド japanese には国語の得点を格納し、フィールド arithmetic には算数の得点を格納します。

そして、Scoreクラスの変数 taro hanako を宣言・生成します。 インスタンス taro には太郎君の得点を格納し、インスタンス hanako には花子さんの得点を格納します。 最後に、すべての得点を合計し、4で割ります。

余力のある人は、コンストラクターも定義したクラスScoreを定義してください。

そして、コンストラクターを呼び出して、Scoreクラスの変数 taro には太郎君の得点を格納し、Scoreクラスの変数 hanako には花子さんの得点を格納します。 最後に、すべての得点を合計し、4で割ります。

ScoreMain2.java
class ScoreMain2 {
    static class Score {
        
        
    }
    public static void main (String[] args) {
        
        
        
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'ScoreMain2'
85
PS ...\Desktop\java1>

レポート課題

今日の演習12の答案(Javaプログラム)をメールで提出してください。 差出人は大学発行のメール・アドレス(学生番号@cis.twcu.ac.jp)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(6月27日)を明記してください。


参考文献


[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

2025年6月27日更新
小西 善二郎 <konishi@cis.twcu.ac.jp>
Copyright (C) 2025 Zenjiro Konishi. All rights reserved.