目次 | 索引 |
---|---|
端末エミュレータに"Good morning!"と出力するには、
System.out.println("Good morning!");
と書きました。 では、ダブルクオートも出力するにはどうすればよいでしょうか。 正解は、
System.out.println("\"Good Morning!\"");
です。
文字列"\""がダブルクオートの代りになるように、直接扱いにくい文字の代りとなる文字列を、 エスケープ・シーケンス ( escape sequence ) とよびます。 Javaのエスケープ・シーケンスは以下の通りです。 ここで、タブとは一定のきざみ(たいていは8文字単位)の位置まで設けられる間隔のことです。 データを表のような形式で出力するときに役に立ちます。
\n | 改行 |
\t | タブ |
\b | バックスペース |
\r | 復帰 |
\f | フォームフィード |
\\ | バックスラッシュ |
\' | シングルクオート |
\" | ダブルクオート |
レコード ( record ) とは、いくつかのデータをひとまとめにしたものです。 次の図はレコードのイメージを表しています。
レコードの構成要素を フィールド ( field ) とよびます。
データをまとめたものとして、以前に配列を取り上げました。 レコードと配列には次のような違いがあります。
int[]
などと規則的な名前がつきますが、レコード型には個別に名前がつきます。
ここでレコード型とは、レコードを表すデータ型です。
レコード型の定義は、データ型としての名前、フィールドの名前、およびどのフィールドにどのデータ型が格納できるかの指定で成り立ちます。
ここで、フィールド
hour
と
minute
に整数(
int
型)が格納できるレコード型
Time
を定義します。
上記のレコードは
Time
型と考えることができます。
実は、Javaにはレコードはありません。 しかし、 インスタンス ( instance ) というものがレコードの機能を持っています。 レコードとインスタンスの対応は次の通りです。
一般 | Java |
---|---|
レコード | インスタンス |
フィールド | インスタンス変数 |
レコード型 | クラス |
この授業では、インスタンス、フィールド、およびクラスという用語を用います。 ちなみに、プログラミング言語によっては、レコードのことを構造体とよびます。
レコードとしてのインスタンスを使うには、まずクラスを定義する必要があります。
フィールドに格納するデータが整数(
int
型)でしたら、次のように書きます。
class classname { int fieldname1, ..., fieldnamen; }
ここで、 classname はクラス名、 fieldname はフィールド名です。 上記の例ですと、次のようになります。
/* 1*/ class Time { /* 2*/ int hour, minute; /* 3*/ }
これをファイル(Time.java)に保存します。 (このファイルがありませんと、以下のプログラムは動きません。)
クラスが定義できましたら、プログラムを作成します。 次のプログラムは、変数を宣言し、インスタンスを生成してそこに格納し、インスタンスのフィールドにデータを格納し、その値を表示するものです。
/* 1*/ class TimeTest { /* 2*/ public static void main (String[] args) { /* 3*/ Time x; /* 4*/ x = new Time(); /* 5*/ x.hour = 9; /* 6*/ x.minute = 30; /* 7*/ System.out.println(x.hour + ":" + x.minute); /* 8*/ } /* 9*/ }
b00a001@Ampere:~/java% java TimeTest 9:30 b00a001@Ampere:~/java%
変数に整数(
int
型)を格納するには変数の宣言が必要でした。
変数にインスタンスを格納するにも、同様に変数の宣言が必要です。
これは次のように書きます。
classname variable;
今まで
int
と書いていた部分をクラス名に変えます。
3行目で、変数
x
を
Time
クラスと宣言します。
クラスのインスタンスは、明示的に生成してはじめて使えます。
インスタンスを生成するにはキーワード
new
を用います。
クラス
classname
のインスタンスを生成して、変数
variable
に格納するには、
variable = new classname();
と書きます。
4行目で、
Time
クラスのインスタンスを生成して、変数
x
に格納します。
なお、次のように書きますと、変数の宣言とインスタンスの生成、そしてその変数への格納が同時に行えます。
classname variable = new classname();
インスタンスのフィールドにデータを格納するには、次のような文を用います。
variable.fieldname = expression;
これで、変数
variable
に格納されているインスタンスのフィールド
fieldname
に、式
expression
の値が格納されます。
5行目で、インスタンス
x
の
hour
フィールドに9が格納され、6行目で、
minute
フィールドに30が格納されます。
インスタンスのフィールドに格納されたデータを取り出すには、式
variable.fieldname
を用います。
この式の値は、変数
variable
に格納されているインスタンスのフィールド
fieldname
に格納されているデータです。
7行目で、インスタンス
x
の
hour
フィールドと
minute
フィールドからデータを取り出して、出力します。
これまで扱った配列は、要素が整数(
int
型)のものだけでした。
以下のようにしますと、要素がクラスのインスタンスである配列が使えます。
要点は、これまで
int
と書いていた部分に、クラス名
classname
を書くことです。
まず、変数の宣言は
classname[] arrayname;
と書きます。 大きさが size である配列を生成して変数 arrayname に格納するには次のようにします。
arrayname = new classname[size];
このふたつは次のようにまとめられます。
classname[] arrayname = new classname[size];
この段階では、まだ配列の要素には何も格納されていません。 インスタンスを生成して、配列の各要素に格納する必要があります。 これは、例えば次のようにします。
int i; ... for (i = 0; i < arrayname.length; i++) { arrayname[i] = new classname(); }
配列の要素に格納されたインスタンスのフィールドへの代入は、文
arrayname[index].fieldname = expression;
によって行います。 式
arrayname[index].fieldname
によってこの値が取り出せます。
次のプログラムは、配列に3つの時刻データを格納し、それを画面に出力するものです。
4行目で、
Time
クラスの配列の変数
a
を宣言し、配列を生成して
a
に格納します。
5行目から7行目までで、インスタンスを生成して配列の各要素
a[i]
に格納します。
これで、インスタンスのフィールドに整数が格納できます。
8行目から10行目までで、フィールドに整数を格納し、12行目でそれを取り出します。
/* 1*/ class Time { /* 2*/ int hour, minute; /* 3*/ }
/* 1*/ class TimeArray { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ Time[] a = new Time[3]; /* 5*/ for (i = 0; i < a.length; i++) { /* 6*/ a[i] = new Time(); /* 7*/ } /* 8*/ a[0].hour = 13; a[0].minute = 15; /* 9*/ a[1].hour = 14; a[1].minute = 55; /*10*/ a[2].hour = 16; a[2].minute = 35; /*11*/ for (i = 0; i < a.length; i++) { /*12*/ System.out.println(a[i].hour + ":" + a[i].minute); /*13*/ } /*14*/ } /*15*/ }
b00a001@Ampere:~/java% java TimeArray 13:15 14:55 16:35 b00a001@Ampere:~/java%
クラスのインスタンスを扱う場合、これまでは、生成してからフィールドに値を格納しました。 例えば次のように書きました。
Time x = new Time(); x.hour = 13; x.minute = 15;
変数や配列では、初期化を使ってプログラムを短くしました。 インスタンスでも、 コンストラクタ ( constructor ) というものを用いますと、初期化に相当することができます。 上記の例ですと、例えば次のように書けます。
Time x = new Time(13, 15);
もしクラスが
class classname { int fieldname1, ..., fieldnamen; }
と定義されているのでしたら、次のように定義し直しますと、コンストラクタが使えるようになります。
class classname { int fieldname1, ..., fieldnamen; classname (int fieldname1, ..., int fieldnamen) { this.fieldname1 = fieldname1; ... this.fieldnamen = fieldnamen; } }
これで、式
を呼び出しますと、フィールド fieldname 1 に値 argument 1 を格納し、…、 fieldname n に argument n を格納したインスタンスになります。
コンストラクタはメソッドに似ています。 どちらも、あらかじめ定義しておき、呼出しによってその機能が働きます。 コンストラクタとメソッドは以下の点が異なります。
void
や
int
などと書いて、返り値の型を指定しました。
コンストラクタ定義では、返り値の型は指定しません。
new
を用います。
次のプログラムでは、チャイムの時刻を表すクラス
Chime
を定義しています。
Chime.java の3行目から6行目までが、コンストラクタ定義です。
このコンストラクタは、第1引数を
hour
フィールドに格納し、第2引数を
minute
フィールドに格納します。
ChimeTest.java の3行目で、このコンストラクタが呼び出され、
hour
フィールドに10が格納され、
minute
フィールドに30が格納されます。
/* 1*/ class Chime { /* 2*/ int hour, minute; /* 3*/ Chime (int hour, int minute) { /* 4*/ this.hour = hour; /* 5*/ this.minute = minute; /* 6*/ } /* 7*/ }
/* 1*/ class ChimeTest { /* 2*/ public static void main (String[] args) { /* 3*/ Chime c = new Chime(10, 30); /* 4*/ System.out.println(c.hour + ":" + c.minute); /* 5*/ } /* 6*/ }
b00a001@Ampere:~/java% java ChimeTest 10:30 b00a001@Ampere:~/java%
配列の初期化が、ブレースの括弧内に要素を並べて書くとできることを思い出してください。 これとコンストラクタを組み合わせますと、インスタンスの配列の初期化が極めてコンパクトに書けます。
次のプログラムでは、4行目から6行目で、3つ時刻データからなるインスタンスの配列を
a
に格納しています。
上記の TimeArray.java と比べてみてください。
/* 1*/ class ChimeArray { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ Chime[] a = {new Chime(10, 30), /* 5*/ new Chime(10, 55), /* 6*/ new Chime(12, 25)}; /* 7*/ for (i = 0; i < a.length; i++) { /* 8*/ System.out.println(a[i].hour + ":" + a[i].minute); /* 9*/ } /*10*/ } /*11*/ }
b00a001@Ampere:~/java% java ChimeArray 10:30 10:55 12:25 b00a001@Ampere:~/java%
注意1. 上記のコンストラクタは、「典型的なコンストラクタ」と呼ぶべきものです。 一般的には、コンストラクタはより複雑な機能を持ちます。
注意2.
上記のようにコンストラクタを定義しますと、
new Chime()
ではインスタンスが生成できなくなります。
実は、これは引数なしのコンストラクタであり、明示的にコンストラクタが定義されないときに限り、自動的に用意されるものです。
引数ありのコンストラクタと引数なしのコンストラクタを両方使うには、次のようにします。
class Chime { int hour, minute; Chime () { } Chime (int hour, int minute) { this.hour = hour; this.minute = minute; } }
インスタンスの例として、以下のような長方形をインスタンスの配列に格納し、その総面積を計算します。
幅 | 高さ | |
---|---|---|
0 | 20 | 30 |
1 | 50 | 10 |
2 | 40 | 20 |
3 | 10 | 70 |
4 | 60 | 10 |
ファイル Rectangle.java では、幅と高さを格納するために、
Rectangle
というクラスを定義します。
width
というフィールドには幅を、
height
というフィールドには高さを格納します。
コンストラクタは、引数が幅、高さの順になるように定義します。
/* 1*/ class Rectangle { /* 2*/ int width, height; /* 3*/ Rectangle (int width, int height) { /* 4*/ this.width = width; /* 5*/ this.height = height; /* 6*/ } /* 7*/ }
ファイル RectangleMain.java では、次のようにコンストラクタを呼び出して、配列 rects にすべての幅と高さを格納します。
Rectangle[] rects = {new Rectangle(20, 30), new Rectangle(50, 10), new Rectangle(40, 20), new Rectangle(10, 70), new Rectangle(60, 10)};
アルゴリズムは次のようになります。
Rectangle
の配列の変数
rects
を宣言し、上記の要領で初期化する。
プログラムは以下のようになります。
/* 1*/ class RectangleMain { /* 2*/ public static void main (String[] args) { /* 3*/ int i, area, areaSum = 0; /* 4*/ Rectangle[] rects = {new Rectangle(20, 30), /* 5*/ new Rectangle(50, 10), /* 6*/ new Rectangle(40, 20), /* 7*/ new Rectangle(10, 70), /* 8*/ new Rectangle(60, 10)}; /* 9*/ System.out.println("No.\tWidth\tHeight\tArea"); /*10*/ for (i = 0; i < rects.length; i++) { /*11*/ area = rects[i].width * rects[i].height; /*12*/ areaSum = areaSum + area; /*13*/ System.out.print(i + "\t"); /*14*/ System.out.print(rects[i].width + "\t"); /*15*/ System.out.print(rects[i].height + "\t"); /*16*/ System.out.println(area); /*17*/ } /*18*/ System.out.println("Total\t\t\t" + areaSum); /*19*/ } /*20*/ }
b00a001@Ampere:~/java% java RectangleMain No. Width Height Area 0 20 30 600 1 50 10 500 2 40 20 800 3 10 70 700 4 60 10 600 Total 3200 b00a001@Ampere:~/java%
ある中学で、5人の生徒が英語、数学、および国語の試験を受け、以下のような得点になったとします。 これらの得点をいったんインスタンスの配列に格納し、生徒ごとの平均点、科目ごとの平均点、および全体の平均点を計算し、もとの得点とあわせて表の形式で出力するプログラムを作成してください。 (便宜上、出席番号は0から始めます。)
出席番号 | 英語 | 数学 | 国語 |
---|---|---|---|
0 | 70 | 60 | 80 |
1 | 60 | 60 | 70 |
2 | 90 | 80 | 90 |
3 | 90 | 80 | 80 |
4 | 70 | 80 | 80 |
ファイル Student.java では、得点を格納するために、
Student
というクラスを定義します。
eng
というフィールドには英語の得点を、
math
というフィールドには数学の得点を、
jpn
というフィールドには国語の得点を、それぞれ格納します。
コンストラクタは、引数が英語、数学、国語の順になるように定義します。
ファイル StudentMain.java では、次のようにコンストラクタを呼び出して、配列 stds にすべての得点を格納します。 (コピー・アンド・ペーストして使ってください。)
Student[] stds = {new Student(70, 60, 80), new Student(60, 60, 70), new Student(90, 80, 90), new Student(90, 80, 80), new Student(70, 80, 80)};
アルゴリズムは次のようにします。
Student
の配列の変数
stds
を宣言し、上記の要領で初期化する。
b00a001@Ampere:~/java% java StudentMain No. Eng. Math. Jpn. Avg. 0 70 60 80 70 1 60 60 70 63 2 90 80 90 86 3 90 80 80 83 4 70 80 80 76 Avg. 76 72 80 76 b00a001@Ampere:~/java%
今日の演習9に従ってJavaプログラムを作成し、そのプログラムをkonishi@twcu.ac.jpあてにメールで提出してください。 メールには、学生番号、氏名、科目名、授業日(11/21)を明記してください。