Javaプログラミング入門
第4回
今日の
• オブジェクト指向への下準備
• クラスとインスタンス
配列からクラス宣言へ
public class Heikin3 {
public static void main(String[] args) {
int[] ten;
double heikin;
ten = new int[3];
ten[0] = 63;
ten[1] = 90;
ten[2] = 75;
heikin = (ten[0] + ten[1] + ten[2]) / 3.0;
System.out.println("国語は" + ten[0]+ "点");
System.out.println("数学は" + ten[1] + "点");
System.out.println("英語は" + ten[2] + "点");
System.out.println("平均点は" + heikin + "点");
}
}
クラスとは
• 関連した情報を1つにまとめたもの
▫ 「科目の名前」と「点数」は関連した情報
▫ →これらをひとつにまとめる
クラスにする
• 科目クラスを作る
public class Kamoku {
String name;
// 科目名
int score;
// 点数
}
• 「class」はクラス宣言の始まりを表す予約語
• クラス名は大文字で始めるのが慣習
クラス宣言とフィールド
public class クラス名 {
型 フィールド名;
型 フィールド名;
}
インスタンスを作る
• 具体的な情報を作る
▫ 「国語、63点」の場合
Kamoku kokugo = new Kamoku(); //科目を一つ作る
kokugo.name = "国語"; //科目の名前を「国語」
kokugo.score = 63; // 点数を「63点」

• このように「具体的なもの」のことをインスタ
ンスと言う
• インスタンスの作り方
▫ クラス名 変数 = new クラス名();
フィールド
• nameやscoreのように情報を保持する部分を
フィールドと言う
• Kamokuクラスはnameとscoreという2つの
フィールドを持っている
• フィールドへの代入
▫ インスタンス.フィールド名 = 値;
コンストラクタ
• 新しいインスタンスを作って、毎回値を代入す
るのは面倒
• コンストラクタで値を初期化することが出来る
▫ Kamoku kokugo = new Kamoku("国語", 63);
▫ 必要な情報を引数で渡している
コンストラクタの定義
科目クラスのコンストラクタ
public class Kamoku {
String name;
int score;

}

// 科目名
// 点数

// コンストラクタ
public Kamoku(String name, int score) {
this.name = name;
this.score = score;
}
コンストラクタの定義
• Kamokuという名前がクラス名と同じ
• 戻り値の型が書かれていない(voidでもない)
▫ コンストラクタには戻り値は記述しない
this
• 現在のインスタンスを表す
▫ ここでは、「今初期化しようとしているインスタ
ンス」のこと

• thisもJavaの予約語
インスタンスを作る
Kamoku kokugo = new Kamoku("国語", 63);

変数kokugo

kokugoのインスタンス

nameの値は"国語"
scoreの値は63
科目名と点数を表示する時の記述
• これまでの記述だと
Kamoku kokugo = new Kamoku("国語", 63);
System.out.println(kokugo.name + "は" +
kokugo.score + "点");
表示結果
国語は63点
「科目というもの」をいっぺんに記述
したい
• 「科目の名前」と「点数」をバラバラに扱うの
ではなく、いっぺんにまとめて扱いたい

Kamoku kokugo = new Kamoku("国語", 63);
System.out.println(kokugo);
toStringメソッドを使う
@Override
public String toString() {
return this.name + "は" + this.score + "点";
}
• @Overrideはスーパークラスのメソッドを上書
きしているという注釈
Javaの仕様
• 文字列連結の演算子+によってインスタンスを
文字列に変換する時、そのインスタンスの
toStringメソッドを自動的に呼び出すという約束
になっている
System.out.println(kokugo);

と
System.out.println(kokugo.toString());

は同じ動きをする
演習1
• 名前(name)と価格(price)を持つ「製品」を表す
クラスを作りなさい。
また、インスタンスを表示した際に、
[名前,価格]
と表示されるようにしなさい
科目の平均を求めるクラス
public class KamokuHeikin {
public static void main(String[] args) {
Kamoku[] kamokus = {
new Kamoku("国語", 63),
new Kamoku("数学", 90),
new Kamoku("英語", 75),
new Kamoku("理科", 45),
new Kamoku("社会", 81),
};
int sum = 0;
for (int i = 0; i < kamokus.length; i++) {
System.out.println(kamokus[i]);
sum += kamokus[i].score;
}
double heikin = (double) sum / kamokus.length;
System.out.println("平均点は" + heikin + "点");
}
}
フィールドとメソッドの確認
• KamokuHeikinクラスは
▫ どんなフィールドが宣言されているか?
▫ どんなメソッドが宣言されているか?

• クラス宣言を見た時は必ずフィールドとメソッ
ドを確認することが大事
mainメソッド
• 一番初めに実行される特別なメソッド
• staticがついたメソッドは、インスタンスを作ら
なくても使えるメソッド
• staticメソッドやクラスメソッドと言う
toStringメソッド
• staticメソッドではない
• 非staticメソッドやインスタンスメソッドと言う
フィールドにも種類がある
• クラスは、フィールドとメソッドを持っている
• メソッドには、インスタンスメソッドとクラス
メソッドの2種類がある
• フィールドには、インスタンスフィールドとク
ラスフィールドの2種類がある
インスタンス配列の初期化
• 今回は「科目クラスの配列」を宣言
Kamoku[] kamokus = {
....
};
• 前は、
int[] tens = {
....
};
とint型の配列を宣言していた
クラスは参照型
• クラスはプリミティブ型と参照型の2種類あるう
ちの参照型にあたる
フィールドと変数
• 3行目のkamokusは、フィールドではなく、
mainメソッドの中で宣言されている変数
• フィールドは、宣言されているクラスのどのメ
ソッドからでも使用できるが、変数は宣言され
ているメソッドの中でしか使えない
• フィールドと変数は宣言の仕方はほとんど同じ
だが、宣言する場所が違うことに注意
クラス宣言
public class クラス名 {
型 フィールド名;
型 フィールド名;
型 フィールド名;

フィールドの宣言

型 メソッド名( 引数列 ) {
型 変数名;
変数の宣言
}

}

型 メソッド名( 引数列
型 変数名;
}

メソッドの宣言

){
メソッドの宣言
演習2
• 次のプログラムは、3科目の試験の合計点を学生
ごとに表示するプログラムである。学生クラス
(Student.java)を 完成させなさい。
Student.java
public class Student {
String name;
int[] scores;
public Student(String name, int x, int y, int z) {
???
}
@Override
public String toString() {
String s = "[" + name;
for (int i = 0; ???; i++) {
s += ???;
}
s += "]";
return s;
};
public int total() {
int sum = 0;
for (int i = 0; ???; i++) {
???
}
return sum;
}
}
StudentTest.java
public class StudentTest {
public static void main(String[] args) {
Student[] data = {
new Student("陽", 65, 90, 100),
new Student("大引", 82, 73, 64),
new Student("西川", 74, 31, 42),
new Student("中田", 100, 95, 99),
new Student("小谷野", 65, 90, 88)
};
for (int i = 0; i < data.length; i++) {
System.out.println(data[i] + "t->" + data[i].total());
}

}
}
表示結果
[陽,65,90,100] ->255
[大引,82,73,64] ->219
[西川,74,31,42] ->147
[中田,100,95,99]
->294
[小谷野,65,90,88]
->243
クラスとインスタンス
• クラスのインスタンスは共通の性質を持つ
Stringクラス
Stringのインスタンス
Stringのインスタンス

"田中"

"Hello World! "
Stringのインスタンス
"Java"
インスタンス
• インスタンス(instance)は具体的な「特定のも
の」を表す
• すべてのインスタンスはクラスに属している
• インスタンスのことを「オブジェクト」と呼ぶ
こともある。
クラスにはどんなものがあるか
•
•
•
•
•
•

文字列を表すStringクラス
ファイルを表すFileクラス
ファイルを読むためのFileReaderクラス
ファイルを書くためのFileWriterクラス
長さが変化する配列を表すクラスArrayList
Systemクラス、Mathクラスはインスタンスを作
るのが目的ではないが、便利なツールや数学計
算をするための関数などが用意されている
• JDKでは多くのクラスが規定されている
クラスを宣言する
• 新たなクラスを作ること→「クラスを宣言す
る」
• クラス名は大文字で始めるのが慣習
class クラス名 {
フィールドの宣言
メソッドの宣言
}
フィールドとメソッド
• フィールドは変数のようなもの
• メソッドは関数のようなもの
• フィールドとメソッドがクラスの性質を決める
拡張クラスを宣言する
• すでに存在するクラスをもとにして拡張するこ
ともできる
• Threadクラスを拡張してMyThreadクラスを作
る場合
class MyThread extends Thread {
...
}
• extendsはJavaの予約語
インターフェースを実装したクラスを
宣言する
• 抽象的なインターフェースを具体的に実装する
クラスを宣言することも出来る
• Runnableインターフェースを実装した、
MyRunnerというクラスを宣言する場合
class MyRunner implements Runnable {
...
}
• implementsはJavaの予約語
フィールド
• 情報を保存する場所を指す
• 「幅」「高さ」という2つの長方形の情報を持つ
クラス
class Rectangle {
int width:
int height;
}
• この時、widthやheightをフィールドと呼ぶ
• ここではまだクラス宣言しただけ
メソッド
• 情報を処理する方法
• 長方形を表すRectangleクラスに以下のメソッド
を追加する
▫ 幅と高さを設定する(setSize)
▫ 面積を計算する(getArea)
Rectangleクラス
class Rectangle {
int width;
int height;
void setSize(int w, int h) {
width = w;
height = h;
}
int getArea() {
return width * height;
}
}
setSizeメソッド
• void
▫ 情報処理の結果を戻り値として返さない

• メソッド名は小文字で始める
• (int w, int h)は、このメソッドの「仮引数列」で
あり、メソッドの入力にあたる
• 値を設定する場合は、メソッド名は「set~」で
始めることが多い
getAreaメソッド
• はじめのintは、このメソッドの「戻り値の型」
を表す
• 値を取得するメソッドは「get~」で始めること
が多い
• このメソッドの仮引数(入力)はなし
▫ 面積を計算するのに必要な情報はフィールドが保
持しているため
メソッドを宣言しただけでは何も起き
ない
• メソッドは「呼び出し」をしなければ動かない
• メソッドを呼び出すためには、インスタンスを作っ
ておかなければならない
• setSizeメソッドで幅と高さを設定するためには、設
定する対象となる具体的な長方形(インスタンス)が
必要
• getAreaメソッドで面積を計算するには、面積を計
算する対象となる具体的な長方形(インスタンス)が
必要
• ただし、「クラスメソッド」の場合は、インスタン
ス生成は必要ない
インスタンスの作り方
• Rectangleクラスのインスタンスを作るには、
new演算子を使う

new Rectangle()
• newはjavaの予約語
• 作ったインスタンスをRectangle型として宣言し
た変数に代入する
Rectangle r = new Rectangle();
フィールドへのアクセス
Rectangle r = new Rectangle();
r.width = 123;
r.height = 45;
Rectangle型の変数r+「.(ドット)」+Rectangleク
ラスのフィールドwidth
• 「.(ドット)」は、日本語の「の」にあたる
メソッドの呼び出し
Rectangle r = new Rectangle();
r.setSize(123, 45);

• rのsetSizeメソッドを呼び出し、第1引数を123、
第2引数を45をせよ
• 「メソッドを呼び出すときに与える引数」のこ
とを実引数と言う
• 「メソッドの宣言に書かれた引数」のことを仮
引数と言う
this:インスタンスの指定はいつ必要
なのか?
• メソッド宣言の中で使われているフィールド名
やメソッド名の前には、「自分」を表すインス
タンスthisが省略されている
void setSize(int w, int h) {
this.width = w;
this.height = h;
}
• ここでthisはインスタンス自身を表す
コンストラクタとは何か
• 長方形のインスタンスを作るときに、長方形の
大きさを設定する処理は必ず必要
• newでインスタンス生成した後、setSizeを別途
呼び出すのは面倒
• インスタンスを生成するのと同時に、インスタ
ンスの「初期化」をする
• constructとは「構築する」「つくり上げる」と
いう意味
Rectangleのコンストラクタ
public Rectangle(int w, int h) {
width = w;
height = h;
}
• メソッドと似ているが異なる点が2点
1. コンストラクタには戻り値の型がない(voidでもな
い)
2. コンストラクタの名前はクラス名と同じ

• コンストラクタの中から他のメソッド(setSize)を
呼び出してもよい
コンストラクタを呼び出す
Rectangle r = new Rectangle(123, 45);
• 幅123、高さ45のRectangleのインスタンスが生
成され、変数rに代入された
引数なしコンストラクタ
• 引数を指定しない時のインスタンスの初期化を
記述するのが引数なしコンストラクタ

• 幅も高さも指定しない場合、幅は10、高さ20に
初期化するコンストラクタ
Rectangle() {
setSize(10, 20);
}
コンストラクタは複数定義出来る
• 引数列が異なっていれば、1つのクラスにコンス
トラクタが複数あっても構わない
• コンストラクタが1つも宣言されていないクラス
の場合は、引数なしのコンストラクタが自動的
に生成される
▫ これをデフォルトコンストラクタと呼ぶ
Rectangle () {
super();
}
フィールドの初期化
• 単にフィールドを初期化するだけなら、コンス
トラクタの中で設定せずに、フィールド宣言の
ところに初期値を記述すればよい
int width = 10;
int height = 20;
フィールドの初期値
• 初期化されていないフィールドの初期値は以下
のようになる
型

初期値

boolean型

false

整数型

0

浮動小数点数型

0.0

参照型

null

• 初期化されていないフィールドの値は、その型
に応じて初期化されるが、初期化されていない
変数は未定義になる
mainメソッド
• Rectangleクラスにmainメソッドを追記してみる
public static void main(String[] args) {
Rectangle r1 = new Rectangle();
System.out.println("r1.width = " + r1.width);
System.out.println("r1.height = " + r1.height);
System.out.println("r1.getArea() = " + r1.getArea());
Rectangle r2 = new Rectangle(123, 45);
System.out.println("r2.width = " + r2.width);
System.out.println("r2.height = " + r2.height);
System.out.println("r2.getArea() = " + r2.getArea());
}
インスタンスはどこに作られるのか?
Rectangle r1;
• と変数が宣言されるとき、Rectangle型の変数r1
が確保される
• →Rectangleクラスのインスタンスを参照する領
域が確保され、それにr1という名前が付けられ
る
• 変数r1が作られても、まだRectangleクラスのイ
ンスタンスは作られた訳ではない
▫ newした時に初めてインスタンスが生成される
スタックとヒープ
• 変数r1が確保されている領域をスタック(stack)
と呼ぶ
• Rectangleのインスタンスが確保されている領域
をヒープ(heap)と呼ぶ
演習3
• widthフィールドが12で、heightフィールドが34
であるようなRectangleのインスタンスを表示し
たとき、
Rectangle(12, 45)
と表示されるようにしなさい
クラスフィールドとは
• 「インスタンスに個別の番号をつけるにはどう
したらよいか?」
class Rectangle {
int number;
Rectangle() {
number = ...
}
}
• numberフィールドはどこにいる?
全インスタンス共通のどこかに情報を
保持しておくには?
• numberフィールドは、新たに作られたばかりの
インスタンスの中にあるフィールド
• つまり、自分以外のインスタンスがどれくらい
あるのかわからない
• 全体を俯瞰して見る場所が必要
▫ Javaではクラスフィールド(クラス変数、スタ
ティックフィールド)と呼ばれる宣言をすること
で、全インスタンス共通の情報を保持することが
出来る
クラスフィールドの宣言
class Rectangle {
static int counter = 0;
}
• 通常のインスタンスとは異なり、staticという修
飾子が付く
• staticは「静的な」という意味
クラスフィールドを使ってインスタン
スに番号をつける
class Rectangle {
...
static int counter = 0;
int number;
Rectangle() {
...
number = counter;
counter++;
}
}
クラスメソッドの宣言
• メソッドにもインスタンス同様staticを使ったクラ
スメソッドがある
• 「これまでに作られたRectangle インスタンスの個
数を得る」メソッドgetCounter
class Rectangle {
static int counter = 0;
...
static int getCounter() {
return counter;
}
}
クラスメソッド
• staticをメソッドに付けるとクラスメソッドにな
る
• クラスメソッドは特定のインスタンスと関連付
けられていない
• 「現在のインスタンス」thisを使うとコンパイ
ルエラー
• superを使ってもコンパイルエラー
• staticではないメソッドをインスタンスメソッド
と言う
クラスメソッドとインスタンスメソッ
ド
• GamePlayerクラスで「生きているプレイヤーの数」を
得るcountAlivePlayerはクラスメソッド。これに対して、
「現在のプレイヤーが生きているかどうか」を調べるの
isAliveメソッドはインスタンスメソッド
class GamePlayer {
....
static int countAlivePlayer() {
...
}
boolean isAlive() {
...
}
}
クラスメソッドの呼び出し
• クラスメソッドは特定のインスタンスに紐付か
ないので以下のようにアクセス出来る

• クラス名.メソッド名(引数列)
getAreaメソッドを2通りで書いてみる
• getAreaメソッドをクラスメソッドとして書く
class Rectangle {
int width;
int height;
int getArea() {
return this.width * this.height;
}
}
getAreaメソッドを2通りで書いてみる
• getAreaメソッドをクラスメソッドとして書く
class Rectangle {
int width;
int height;
static int getArea(Rectangle obj) {
return obj.width * obj.height;
}
}
mainメソッド
• クラスを1つのアプリケーションとして動作させ
るときのmainメソッドは、staticが付いている
ので、クラスメソッドになる
• publicは、「パッケージの外から呼び出せる」
という意味。詳細は後日。
• 引数で渡されている配列argsは、このクラスを
実行しようとした時の入力値(コマンドラインパ
ラメータ)
クラスメソッドだけのクラス
• java.lang.Mathクラスは数学的な計算を行うため
のクラス
• Mathクラスにはすべてクラスメソッドとして宣
言されている
• Mathクラスのようにクラスメソッドだけを集め
たクラスの目的は、インスタンスを作ることで
はなく、関連したメソッドを1箇所にまとめるこ
と(ユーティリティクラスと呼ぶこともある)
修飾子
• final
▫ 最終的なものであり、変更不可であることを表す。
クラスやインターフェースなら拡張できないこと
を表し、インスタンスフィールドやクラスフィー
ルドであれば、定数を表す。メソッドの場合は、
上書き定義(オーバーライド)出来ないことを示す。
▫ finalフィールドの場合は全て大文字で定義する

• abstract
▫ 抽象クラスや抽象メソッドであることを表す
修飾子
• static
▫ クラスフィールドやクラスメソッドであることを
表す

• synchronized(シンクロナイズド)
▫ 詳しくは後日

• native
▫ Java言語以外の言語(CやC++)で書かれたメソッド
(ネイティブメソッド)であることを表す
toStringメソッドとequalsメソッド
• toStringメソッドは、クラス階層の最上位である
Objectクラスで実装されており、すべてのクラ
スに継承されている。このため、すべてのクラ
スが潜在的にtoStringメソッドを持っていること
になる
• Objectクラスは他のオブジェクトとの同一性を
調べるequalsメソッドも持っており、これに
よってすべてのオブジェクトは他のオブジェク
トと同一性を調べることが出来る
演習4
• ゲームのプレイヤーを表すクラスGamePlayerを
作り、動かしたところ
[player:Mad Hatter]
[player:Cheshire cat]
[player:Alice]

と表示したかったのだが、3人とも
[player:Alice]と表示されてしまった。
GamePlayer.javaを正しく直しなさい。
GamePlayer.java
public class GamePlayer {
public static String playerName;
public GamePlayer(String name) {
playerName = name;
}
@Override
public String toString() {
return "[player:" + playerName + "]";
}
public static void main(String[] args) {
GamePlayer[] players = new GamePlayer[3];
players[0] = new GamePlayer("Mad Hatter");
players[1] = new GamePlayer("Cheshire cat");
players[2] = new GamePlayer("Alice");
for (int i = 0; i < players.length; i++) {
System.out.println(players[i]);
}
}
}
演習5
• Rectangleのインスタンスの内容が等しいかどう
かを調べるメソッドが必要になり、areSameメ
ソッドを作った。しかし、先生に見せたところ、
「引数を1つにした方がいい」と言われた。どう
すればよいか。
Rectangleクラス
class Rectangle {
...
// 2つのRectangleを比較して、等しかったらtrue,
// 等しくなかったらfalseを返す
boolean areSame(Rectangle a, Rectangle b) {
if (a == null || b == null) {
return false;
} else if (a.width == b.width && a.height == b.height) {
return true;
} else {
return false;
}
}
}
演習6
• これまでのRectangleクラスの宣言では、width
やheightの値がマイナスであるかどうかの
チェックが入っていない。ここで、widthと
heightがマイナスになるなら、強制的に0になる
ように既存のRectangleクラスを修正しなさい。
演習7
• これまでのRectangleクラスは、幅と高さを持つ
長方形だったが、これに「左上すみの位置」を
表すxとyというフィールドを追加し、以下のコ
ンストラクタやメソッドを宣言しなさい
1. フィールド
1. 指定がないときの幅と高さ
(INITIAL_WIDTH,INITIAL_HEIGHT)
演習7(続き)
2. コンストラクタ
1. 引数がないもの(width, heightの初期値は
INITIAL_WIDTH,INITIAL_HEIGHT,xとyは0)
2. width,heightだけを指定したもの(xとyは0)
3. x,y,width,heightを指定したもの
演習7(続き)
3. メソッド
1. 位置を指定するvoid setLocation(int x, int y)メソッ
ド
2. 大きさを指定するvoid setSize(int width, int
height)メソッド
3. [x, y, width, height]の形式で文字列として表現す
るtoStringメソッド
4. 長方形の「重なり部分」(これも長方形)を得る
intersect(Rectangle r)メソッド。ただし、重なり
がない場合はnullを返す。重なりがある場合は、
長方形として返す。
参考文献
• Java言語 プログラミングレッスン[第3版]上
▫ 結城浩[著]

• Java言語 プログラミングレッスン[第3版]下
▫ 結城浩[著]

Javaプログラミング入門【第4回】