Java マスター講座:基礎から応用まで(授業資料)
本授業は、Javaプログラミングの基礎から応用までを体系的に学習する全17回の演習科目である。JavaTutor、Paiza.IO、OnlineGDBを演習環境として使用し、各回で理論説明と実践演習を組み合わせた構成となっている。
カリキュラム構成
本授業は以下の4つの部で構成される。
- 第1部:プログラミング基礎(pi-1〜pi-6)
プログラミングの基本概念から始まり、変数、データ型、メソッド、条件分岐、コレクション、繰り返しを習得する。
- 第2部:オブジェクト指向プログラミング(pi-7〜pi-11)
クラス、メソッド、コンストラクタ、継承、ジェネリクス、多相性、インターフェイス、デザインパターンを学ぶ。
- 第3部:応用技術(pi-12〜pi-14)
時間処理、疑似乱数、タイマー、イベント処理、ソケット通信を学習する。
- 第4部:設計と品質(pi-15〜pi-17)
カプセル化、MVCモデル、テスト、例外処理、プログラム設計を学び、ソフトウェア開発の実践力を養う。
学習内容一覧
| 回 | タイトル | 主要な学習内容 |
|---|---|---|
| pi-1 | プログラミング入門 | プログラミングの基本概念 |
| pi-2 | Java プログラミングの基本 | 変数、データ型、基本構文 |
| pi-3 | 式の抽象化とメソッド | メソッドの定義と呼び出し |
| pi-4 | 条件分岐, ステップ実行 | if文、デバッグ手法 |
| pi-5 | コレクション,リスト,マップ | データ構造の基礎 |
| pi-6 | 繰り返し(ループ) | for文、while文 |
| pi-7 | クラス,メソッド,オブジェクト生成(コンストラクタ) | クラス定義、コンストラクタ |
| pi-8 | クラス設計 | オブジェクト指向設計の基礎 |
| pi-9 | スーパークラス,サブクラス,継承 | 継承、クラス階層 |
| pi-10 | コレクション,ジェネリクス | 型パラメータ、汎用コレクション |
| pi-11 | 多相性,インターフェイス,デザインパターン | ポリモーフィズム、設計パターン |
| pi-12 | 時間,スリープ,疑似乱数,タイマー | 時間処理、乱数生成 |
| pi-13 | 今までの総まとめ | 基礎〜応用の統合演習 |
| pi-14 | イベント,イベントハンドラ,ソケット通信 | イベント駆動、ネットワーク通信 |
| pi-15 | カプセル化,MVCモデル,オブジェクトのマッピング | 情報隠蔽、アーキテクチャパターン |
| pi-16 | プログラムのテスト,アサーション,例外処理 | テスト手法、エラー処理 |
| pi-17 | プログラム設計 | 設計手法、開発プロセス |
到達目標
本授業を修了した受講者は、Javaを用いたプログラム作成ができるようになる。また、オブジェクト指向プログラミングの概念を理解し、クラス設計、継承、多相性を活用したソフトウェア開発ができるようになる。
授業の特徴
本授業は、JavaTutor、Paiza.IO、OnlineGDBによるオンライン演習環境を活用し、理論と実践の両面からJavaプログラミングを習得できる構成となっている。基礎的な文法、オブジェクト指向、MVCモデル、デザインパターンを扱う。実践的なソフトウェア開発能力を養成する。
【関連する外部ページ】
- OnlineGDB の URL: https://www.onlinegdb.com/
- JavaTutor のURL:https://pythontutor.com/java.html
1. プログラミング入門
資料:pi-1. プログラミング入門 [PDF], [パワーポイント]
Java Tutorは、Javaなどのプログラミング言語を体験・演習できるオンラインサービスである。 編集画面は以下の要素で構成される。 プログラム実行手順
使用上の注意
以下の点について考察すること。 GDB onlineは、Javaプログラムの実行に使用できる別のオンラインサービスである。演習パート(クリックして展開)
Java Tutor の基本操作
課題1
public class YourClassNameHere {
public static void main(String[] args) {
System.out.println(1.0/3.0);
}
}
課題2
public class YourClassNameHere {
public static void main(String[] args) {
System.out.println(6 * 1.1);
}
}
課題3
public class YourClassNameHere {
public static void main(String[] args) {
System.out.println(3 * 1.1);
}
}
考察のポイント
補足:GDB online での実行
使用手順
2. Java プログラミングの基本
資料:pi-2. Java プログラミングの基本 [PDF], [パワーポイント]
起動手順
実行手順
注意点
演習では整数型(int)と文字列型(String)を使用する。以下にJavaの主なデータの種類を示す。 基本データ型
その他
整数型(int)の変数を宣言し、値を代入する方法を理解する。 用語
手順
ヒント
文字列型(String)の変数を宣言し、文字列を代入する方法を理解する。 手順 ヒント
演習パート(クリックして展開)
事前準備:Java Tutorの起動と操作
Javaのデータの種類
分類 型名 サイズ 整数 byte 8 bit short 16 bit int 32 bit long 64 bit 浮動小数 float 32 bit double 64 bit 文字 char 16 bit 真偽値 boolean -
演習1:整数型変数の宣言と代入
public class YourClassNameHere {
public static void main(String[] args) {
int x = 100;
}
}
演習2:文字列型変数の宣言と代入
public class YourClassNameHere {
public static void main(String[] args) {
String s = "abc";
}
}
3. 式の抽象化とメソッド
資料:pi-3. 式の抽象化とメソッド [PDF], [パワーポイント]
起動手順
実行手順
注意点
整数型の変数を宣言し、加算の結果を確認する。 手順
ヒント
代入とは、「x = 100」のように書くことで変数xの値を100に設定する操作である。int型(整数型)は整数を扱うデータ型である。System.out.println()は、括弧内の値を画面に出力する命令である。 乗算演算子を使った式の結果を確認する。 手順
ヒント
Javaでは乗算に「*」記号を使用する。演習1-1のプログラムとの違いは演算子のみである。式が異なれば、実行結果も異なることを確認すること。 括弧を含む式の評価順序を理解する。 手順
ヒント
括弧内の式が先に評価される。このプログラムでは、(x + 10)が先に計算され、その結果にyを掛ける。数学と同じ優先順位の規則が適用される。 小数を扱うデータ型を使った計算を実行する。 手順
ヒント
三角形の面積は「底辺 × 高さ ÷ 2」で計算する。double型(浮動小数点型)はint型と異なり小数を扱える。変数名にはローマ字も使用できる。 類似した複数の式を変数で1つにまとめる「抽象化」と、メソッドの定義・使用方法を理解する。 手順
ヒント
100 * 1.1、150 * 1.1、400 * 1.1という類似した式を、変数aを使って「a * 1.1」という1つの式にまとめている。これが抽象化である。メソッド(オブジェクトに属する操作や処理)fooは、式「a * 1.1」に名前fooを付けたものと考えることができる。引数(ひきすう)とは、メソッドに渡す値のことである。returnは、メソッドの計算結果を呼び出し元に返す命令である。 メソッド呼び出しの動作を観察するため、ステップ実行の準備をする。 手順
ヒント
「First」ボタンでプログラムの実行状態を最初に戻すことができる。ステップ実行(プログラムを1ステップずつ実行して動作を観察する機能)の準備として、まず最初の状態に戻す。 プログラム全体のステップ数と、実行開始前の状態を確認する。 手順
ヒント
このプログラムは全部で17ステップある。ステップ数とプログラムの行数は異なる。赤い矢印は「次に実行される行」を示す。プログラム開始時点では変数はまだ生成されていない。 メソッド呼び出し時に実行位置がmainメソッドとfooメソッドの間で移動する様子を観察する。 手順
ヒント
foo(100)が呼び出されると、実行位置がmainメソッドからfooメソッドへ移動する。fooメソッドの処理が終わると、mainメソッドの次の行に戻る。foo(150)、foo(400)でも同様の動作が発生する。 メソッド内の変数が生成・消去されるタイミングを理解する。 手順
ヒント
緑の矢印は「いま実行が終わった行」を示す。メソッド呼び出しでは、実行位置の移動だけでなく変数の生成と消去が自動で行われる。fooメソッドの引数aは、fooメソッドの実行中のみ存在し、処理終了後に自動的に消去される。演習パート(クリックして展開)
事前準備:Java Tutorの起動と操作
演習1-1:変数を使った加算
public class YourClassNameHere {
public static void main(String[] args) {
int x = 100;
int y = 200;
System.out.println(x + y);
}
}
演習1-2:変数を使った乗算
public class YourClassNameHere {
public static void main(String[] args) {
int x = 100;
int y = 200;
System.out.println(x * y);
}
}
演習1-3:複合式の計算
public class YourClassNameHere {
public static void main(String[] args) {
int x = 100;
int y = 200;
System.out.println((x + 10) * y);
}
}
演習1-4:三角形の面積計算
public class YourClassNameHere {
public static void main(String[] args) {
double teihen = 2.5;
double takasa = 5;
System.out.println(teihen * takasa / 2);
}
}
演習2-1:メソッドによる式の抽象化
public class YourClassNameHere {
public static double foo(double a) {
return a * 1.1;
}
public static void main(String[] args) {
System.out.println(foo(100));
System.out.println(foo(150));
System.out.println(foo(400));
}
}
演習3-1:ステップ実行の準備
演習3-2:ステップ数と初期状態の確認
演習3-3:メソッド間のジャンプの観察
演習3-4:変数の生成と消去の観察
全体のまとめ
4. 条件分岐, ステップ実行
資料:pi-4. 条件分岐, ステップ実行 [PDF], [パワーポイント]
起動手順
実行手順
注意点
条件式が真のとき、if節が実行されることを確認する。 手順
ヒント
条件式「age <= 12」は「ageが12以下」を意味する。age=10は12以下であるため、条件式は真となる。 目的
条件式が偽のとき、else節が実行されることを確認する。 手順
ヒント
age=20は12以下ではないため、条件式は偽となり、else節が実行される。 目的
ステップ実行で、条件式が偽のときのジャンプを観察する。 手順
ヒント
プログラムは通常、上から順に実行される(逐次実行)。条件分岐では、条件式が偽のときif節をスキップしてelse節へジャンプする。 目的
ステップ実行で、条件式が真のときのジャンプを観察する。 手順
ヒント
条件式が真のとき、if節が実行され、else節はスキップされる。演習3と比較し、ジャンプ先の違いを確認せよ。 条件分岐の知識を応用し、新しいプログラムを作成する。 課題
以下の仕様を満たすプログラムを作成せよ。 手順
ヒント
変更箇所は、変数名、条件式、出力メッセージの3点である。「100未満」は比較演算子「<」で表現する。 まとめ
演習パート(クリックして展開)
事前準備:Java Tutorの起動と操作
演習1:条件分岐の実行(age=10)
public class YourClassNameHere {
public static void main(String[] args) {
int age = 10;
if (age <= 12) {
System.out.println("500 yen");
} else {
System.out.println("1200 yen");
}
}
}
演習2:条件分岐の実行(age=20)
演習3:ステップ実行の観察(else節が実行される場合)
演習4:ステップ実行の観察(if節が実行される場合)
演習5:条件分岐プログラムの作成
5. コレクション,リスト,マップ
資料:pi-5. コレクション,リスト,マップ [PDF], [パワーポイント]
起動手順
実行手順
注意点
リストは、同じ型の要素を順序付けて格納するデータ構造である。
要素には0から始まる番号(添字)が付いており、要素の削除や挿入によりサイズが増減する。
例:要素 [15, 8, 6, 32, 23] を持つリストでは、添字0に15、添字1に8、添字2に6が格納されている。
ArrayListクラスを使用して空のリストを生成し、addメソッドで要素を挿入する方法を学ぶ。
以下のプログラムをJava Tutorのエディタに入力し、実行する。
オブジェクトmが生成されていることを確認する。
Java Tutorにはコレクションの要素を表示する機能がないため、この演習ではオブジェクトの生成のみを確認する。
プログラムは以降の演習でも使用するため、消さずに残しておくこと。
補足
sizeメソッドを使用してリストの要素数を取得する方法を学ぶ。
演習1のプログラムを以下のように修正し、実行する。
出力結果が「5」であることを確認する。
補足
indexOfメソッドを使用してリスト内の要素を検索し、その添字を取得する方法を学ぶ。
演習2のプログラムを以下のように修正し、実行する。
出力結果が「2」であることを確認する。
なぜ「2」になるのか考えること。
補足
VisualGoを使用して、リストへの要素挿入を視覚的に体験する。
以下の手順で操作する。 補足
マップは、キーと値(バリュー)のペアを格納するデータ構造である。
同じキーは2回以上登場しない(キーは一意である)。
例:キー1に値"Red"、キー2に値"Yellow"、キー3に値"Blue"を持つマップでは、キー2を指定すると値"Yellow"を取得できる。
HashMapクラスを使用して空のマップを生成し、putメソッドでキーと値のペアを挿入する方法を学ぶ。
以下のプログラムをJava Tutorのエディタに入力し、実行する。
出力結果が「3」であることを確認する。
補足
getメソッドを使用してキーから値を取得する方法を学ぶ。
演習5のプログラムを以下のように修正し、実行する。
出力結果が「Yellow」であることを確認する。
getメソッドの引数を1や3に変更して、結果がどう変わるか確認すること。
補足
複数のデータを扱う場合、コレクションを使用すると検索、挿入、削除を効率的に行える。
演習パート(クリックして展開)
事前準備:Java Tutorの起動と操作
リストとは
演習1:リストの生成と要素の挿入
import java.util.ArrayList;
public class YourClassNameHere {
public static void main(String[] args) {
ArrayList<String> m = new ArrayList<String>();
m.add("15");
m.add("8");
m.add("6");
m.add("32");
m.add("23");
}
}
演習2:リストのサイズ取得
import java.util.ArrayList;
public class YourClassNameHere {
public static void main(String[] args) {
ArrayList<String> m = new ArrayList<String>();
m.add("15");
m.add("8");
m.add("6");
m.add("32");
m.add("23");
System.out.println(m.size());
}
}
演習3:リストの検索
import java.util.ArrayList;
public class YourClassNameHere {
public static void main(String[] args) {
ArrayList<String> m = new ArrayList<String>();
m.add("15");
m.add("8");
m.add("6");
m.add("32");
m.add("23");
System.out.println(m.indexOf("6"));
}
}
ArrayListクラスの主なメソッド
演習4:VisualGoでのリスト操作
マップとは
演習5:マップの生成と要素の挿入
import java.util.HashMap;
public class YourClassNameHere {
public static void main(String[] args) {
HashMap<Integer, String> x = new HashMap<Integer, String>();
x.put(1, "Red");
x.put(2, "Yellow");
x.put(3, "Blue");
System.out.println(x.size());
}
}
演習6:マップの検索
import java.util.HashMap;
public class YourClassNameHere {
public static void main(String[] args) {
HashMap<Integer, String> x = new HashMap<Integer, String>();
x.put(1, "Red");
x.put(2, "Yellow");
x.put(3, "Blue");
System.out.println(x.get(2));
}
}
HashMapクラスの主なメソッド
まとめ
6. 繰り返し(ループ)
資料:pi-6. 繰り返し(ループ) [PDF], [パワーポイント]
起動手順
実行手順
注意点
配列(同じ型のデータの並びで、0から始まる番号である添字が付いたもの)を作成し、特定の要素にアクセスする方法を学ぶ。 手順
ヒント
この演習は3つのパートで構成される。配列とfor文を組み合わせた処理を段階的に学ぶ。 for文(変数の値を変化させながら処理を繰り返す構文)を使用し、配列の全要素に対して同じ処理を行う方法を学ぶ。 手順
ヒント
手順
ヒント
手順
ヒント
ステップ実行機能を使用し、プログラムが1行ずつ実行される様子と変数の値の変化を確認する方法を学ぶ。 手順
ヒント
ArrayList(要素の追加・削除によりサイズが変化するリスト)と拡張for文(コレクション(リストやマップなどのデータの集まり)の要素を順にたどるための構文)の使い方を学ぶ。 手順
ヒント
演習パート(クリックして展開)
事前準備:Java Tutorの起動と操作
演習1:配列の基本操作
public class YourClassNameHere {
public static void main(String[] args) {
int days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
System.out.println(days[9]);
}
}
演習2:配列と繰り返し
演習2-a:配列の全要素を表示する
public class YourClassNameHere {
public static void main(String[] args) {
double x[] = {10, 20, 30, 40};
int i;
for(i = 0; i <= 3; i++) {
System.out.println(x[i]);
}
}
}
演習2-b:物体の落下距離を計算する
public class YourClassNameHere {
public static void main(String[] args) {
double x[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int i;
for(i = 0; i <= 10; i++) {
System.out.println((9.8 / 2) * x[i] * x[i]);
}
}
}
演習2-c:配列要素の計算結果を別配列に格納する
public class YourClassNameHere {
public static void main(String[] args) {
double x[] = {8, 6, 4, 2, 3};
double y[] = {0, 0, 0, 0, 0};
int i;
for(i = 0; i <= 4; i++) {
y[i] = x[i] * 1.1;
}
}
}
演習3:ステップ実行
演習4:リストと拡張for文
import java.util.ArrayList;
public class YourClassNameHere {
public static void main(String[] args) {
ArrayList<String> m = new ArrayList<String>();
m.add("15");
m.add("8");
m.add("6");
m.add("32");
m.add("23");
for(String s: m) {
System.out.println(s);
}
}
}
ArrayList<String> は、String型の要素を持つArrayListを意味するm.add("15") は、リストmに文字列"15"を追加するメソッド(オブジェクトに属する操作や処理)の呼び出しであるfor(String s: m) は、リストmの各要素を順番に変数sに代入しながら繰り返す。通常のfor文と異なり、添字を意識せずに全要素を処理できるまとめ
7. クラス,メソッド,オブジェクト生成(コンストラクタ)
資料:pi-7. クラス,メソッド,オブジェクト生成(コンストラクタ) [PDF], [パワーポイント]
起動手順
実行手順
注意点
クラス定義、newによるオブジェクト生成、メソッドアクセスの基本を学ぶ。 背景知識
クラスは、同じ種類のオブジェクトの集まりと考えることができる。例えば「Ball」というクラスを定義すると、半径、場所、色などの属性を持つ複数のボールオブジェクトを作成できる。オブジェクトを生成するには、コンストラクタ(オブジェクト生成のためのメソッド)をnewキーワードとともに使用する。コンストラクタはクラス名と同じ名前を持つ。 手順
ヒント
thisキーワードを使った属性アクセスを学ぶ。 背景知識
メソッドや属性はクラスに属する。メソッド定義内で、そのメソッドが所属するクラスで定義された属性やメソッドにアクセスするときはthis+「.」を使用する。メソッド外ではオブジェクト名+「.」を使用する。 手順
ヒント
オブジェクトの属性を変更するメソッドを定義する。 背景知識 オブジェクトの位置を移動させることを考える。上下左右の移動は、属性xとyを増減することで実現できる。 手順
ヒント
既存のメソッドを再利用して新しいメソッドを定義する。 課題
手順
ヒント
ヒント
演習パート(クリックして展開)
事前準備:Java Tutorの起動と操作
演習1:クラス定義、オブジェクト生成、メソッドアクセス
class Ball {
double x;
double y;
double r;
String color;
public Ball(double x, double y, double r, String color) {
this.x = x;
this.y = y;
this.r = r;
this.color = color;
}
public void printout() {
System.out.println(this.x);
System.out.println(this.y);
System.out.println(this.r);
System.out.println(this.color);
}
}
public class YourClassNameHere {
public static void main(String[] args) {
Ball a = new Ball(8, 10, 1, "blue");
Ball b = new Ball(2, 4, 3, "green");
a.printout();
b.printout();
}
}
Ball a = new Ball(8, 10, 1, "blue");はオブジェクト生成のプログラムである。オブジェクトaが位置(8, 10)、半径1、色blueで生成されるa.printout();はメソッドアクセスのプログラムである。オブジェクト名とメソッド名を「.」で区切る演習2:thisによる属性アクセス
public double dist() {
return this.x + this.y;
}
b.printout();の後に、以下の1行を追加する System.out.println(a.dist());
this.xとthis.yは、そのオブジェクトの属性xとyへのアクセスであるa.dist()は、メソッド外からのアクセスなのでオブジェクト名+「.」を使用している演習3:moveメソッドの定義
public void move(double xx, double yy) {
this.x = this.x + xx;
this.y = this.y + yy;
}
a.move(5, 5);
b.move(10, 10);
a.move(5, 5)を実行すると、オブジェクトaのx座標とy座標がそれぞれ5増加する演習4:right/leftメソッドの定義と応用
this.メソッド名()を使用する
まとめ
8. クラス設計
資料:pi-8. クラス設計 [PDF], [パワーポイント]
起動手順
実行手順
注意点
クラス定義の基本構造を理解し、コンストラクタ(オブジェクト生成時に実行される初期化処理)によるオブジェクト生成の方法を学ぶ。また、文字列を直接指定する方式の問題点を認識する。 手順
ヒント
演習1では、コンストラクタに任意の文字列を渡せるため、不正なデータが混入する可能性があった。この演習では、その問題を解決する別の設計方式を学ぶ。 不正なデータの混入を防ぐクラス設計を学ぶ。コンストラクタで値を設定する代わりに、専用のメソッドを用意する方式を理解する。 手順
ヒント
演習2で作成したSignalクラスを拡張し、信号の状態が自動的に変化するメソッドを追加する。 オブジェクトの属性を「状態」として捉え、メソッドによる「状態変化」を実装する方法を学ぶ。 手順
ヒント
演習3で学んだ状態変化のパターンを、別の例に適用する。 製品のアクティブ/非アクティブ状態を管理するクラスを通じて、状態変化パターンの応用を学ぶ。 手順
ヒント
ここからは、クラス設計とは別の話題として、変数のスコープについて学ぶ。 メソッド内で宣言された変数(ローカル変数)のスコープ(有効範囲)を理解する。メソッドの実行終了とともに変数が自動で消えることを確認する。 手順
ヒント
類似した複数の式を変数とメソッドで抽象化する手法を学ぶ。抽象化を組み合わせることで、より汎用的なコードを作成する方法を理解する。 手順
ヒント
クラス設計と状態変化は、オブジェクト指向プログラミングの基礎となる考え方である。変数のスコープと抽象化は、プログラムの構造を整理し、保守しやすいコードを書くための基本技術である。演習パート(クリックして展開)
事前準備:Java Tutorの起動と操作
演習1:クラス定義とオブジェクト生成(設計例①)
class Signal {
String color;
public Signal(String color) {
this.color = color;
}
}
public class YourClassNameHere {
public static void main(String [] args) {
Signal s = new Signal("red");
}
}
演習2:クラス設計(設計例②)
class Signal {
String color;
public Signal() {};
public void red() { this.color = "red"; };
public void yellow() { this.color = "yellow"; };
public void blue() { this.color = "blue"; };
}
public class YourClassNameHere {
public static void main(String [] args) {
Signal s = new Signal();
s.red();
}
}
演習3:オブジェクトの状態変化(Signal)
class Signal {
String color;
public Signal() {};
public void red() { this.color = "red"; };
public void yellow() { this.color = "yellow"; };
public void blue() { this.color = "blue"; };
public void go() {
if (this.color.equals("blue")) { this.yellow(); }
else if (this.color.equals("yellow")) { this.red(); }
else if (this.color.equals("red")) { this.blue(); }
}
}
public class YourClassNameHere {
public static void main(String [] args) {
Signal s = new Signal();
s.red();
s.go();
}
}
演習4:オブジェクトの状態と状態変化(Product)
class Product {
String s;
public Product() {};
public void active() { this.s = "active"; };
public void deactive() { this.s = "deactive"; };
public void on() {
if (this.s.equals("deactive")) { this.active(); }
}
public void off() {
if (this.s.equals("active")) { this.deactive(); }
}
}
public class YourClassNameHere {
public static void main(String [] args) {
Product p = new Product();
p.deactive();
p.on();
}
}
演習5:メソッド内でのみ使用する変数
public class YourClassNameHere {
public static double foo(double a) {
return a * 1.1;
}
public static void main(String [] args) {
double p;
p = 120;
System.out.printf("%f¥n", foo(p));
p = 200;
System.out.printf("%f¥n", foo(p));
}
}
演習6:抽象化の組み合わせ
public class YourClassNameHere {
public static double x(double a) {
return a * 1.1;
}
public static double y(double b) {
return x(b * 100);
}
public static double z(double c) {
return x(c * 200);
}
public static void main(String [] args) {
System.out.printf("%f¥n", y(5));
System.out.printf("%f¥n", y(12));
System.out.printf("%f¥n", z(8));
System.out.printf("%f¥n", z(16));
}
}
まとめ
9. スーパークラス,サブクラス,継承
資料:pi-9. スーパークラス,サブクラス,継承 [PDF], [パワーポイント]
起動手順
実行手順
注意点
クラスは、同じ種類のオブジェクトの集まりである。「人間」クラスと「学生」クラスがある場合、学生は人間でもある。 サブクラスのオブジェクトは、すべてスーパークラスに属する。「長方形」と「正方形」の関係では、正方形は必ず長方形であるため、長方形がスーパークラス、正方形がサブクラスとなる。 継承とは、スーパークラスの属性とメソッドをサブクラスが受け継ぐ仕組みである。ただし、コンストラクタは受け継がない。 extendsによるスーパークラスの指定と、superによるスーパークラスのコンストラクタ呼び出しを理解する。 手順
ヒント
確認ポイント
メソッドのオーバーライドを理解する。オーバーライドとは、サブクラスでスーパークラスのメソッドを別の定義に置き換えることである。 手順
ヒント
確認ポイント
目的
サブクラスでスーパークラスにない属性やメソッドを追加できることを理解する。 手順
ヒント
確認ポイント
演習パート(クリックして展開)
事前準備:Java Tutorの起動と操作
クラスとオブジェクト
スーパークラスとサブクラス
継承
演習1:継承の基本
class Rectangle {
double x;
double y;
double width;
double height;
public Rectangle(double x, double y, double width, double height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void printout() {
System.out.println(this.x);
System.out.println(this.y);
System.out.println(this.width);
System.out.println(this.height);
}
}
class Square extends Rectangle {
public Square(double x, double y, double size) {
super(x, y, size, size);
}
}
public class YourClassNameHere {
public static void main(String[] args) {
Rectangle a = new Rectangle(4, 8, 1, 2);
Rectangle b = new Rectangle(8, 10, 2, 1);
a.printout();
b.printout();
Square c = new Square(0, 3, 1);
Square d = new Square(1, 1, 2);
c.printout();
d.printout();
}
}
演習2:メソッドのオーバーライド
class Square extends Rectangle {
public Square(double x, double y, double size) {
super(x, y, size, size);
}
public void printout() {
System.out.println(this.x);
System.out.println(this.y);
System.out.println(this.width);
}
}
演習3:サブクラスでの属性の追加
class ColorRectangle extends Rectangle {
String color;
public ColorRectangle(double x, double y, double width, double height, String color) {
super(x, y, width, height);
this.color = color;
}
public void printout() {
System.out.println(this.x);
System.out.println(this.y);
System.out.println(this.width);
System.out.println(this.height);
System.out.println(this.color);
}
}
ColorRectangle e = new ColorRectangle(0, 0, 1, 4, "Red");
e.printout();
まとめ
キーワード一覧
用語 説明 スーパークラス 継承関係において、属性とメソッドを継承されるクラス サブクラス 継承関係において、属性とメソッドを継承するクラス 継承 スーパークラスの属性とメソッドをサブクラスが受け継ぐ仕組み extends スーパークラスを指定するキーワード super スーパークラスのコンストラクタを呼び出すキーワード オーバーライド サブクラスでスーパークラスのメソッドを別の定義に置き換えること
10. コレクション,ジェネリクス
資料:pi-10. コレクション,ジェネリクス [PDF], [パワーポイント]
起動手順
実行手順
注意点
ArrayListの基本的な使い方を理解する。要素の追加と拡張for文による走査を学ぶ。 前提知識
手順
ヒント
Integer型を型変数に指定したArrayListの使い方を理解する。 前提知識
手順
ヒント
異なるクラスのオブジェクトを同一のコレクションで扱う方法を理解する。 前提知識
手順
ヒント
ジェネリクスの仕組みを理解する。自作クラスに型パラメータを導入する方法を学ぶ。 前提知識
手順
ヒント
演習パート(クリックして展開)
事前準備:Java Tutorの起動と操作
演習1:ArrayListの基本操作(String型)
import java.util.ArrayList;
import java.util.Iterator;
public class YourClassNameHere {
public static void main(String[] args) {
ArrayList<String> m = new ArrayList<String>();
m.add("15");
m.add("8");
m.add("6");
m.add("32");
m.add("23");
for(String s : m) {
System.out.println(s);
}
}
}
ArrayList<String>の<String>は型変数である。このリストにはString型のみ格納できるnew ArrayList<String>()で空のリストを生成するfor(String s : m)は、リストmの各要素を変数sに順番に代入しながらループする演習2:ArrayListの基本操作(Integer型)
ArrayList<int>は使用できない
import java.util.ArrayList;
import java.util.Iterator;
public class YourClassNameHere {
public static void main(String[] args) {
ArrayList<Integer> m = new ArrayList<Integer>();
m.add(100);
m.add(200);
m.add(300);
m.add(400);
m.add(500);
for(Integer s : m) {
System.out.println(s);
}
}
}
m.add(100)のように整数を直接渡せるのは、Javaが自動的にint値をIntegerに変換するためであるStringからIntegerに変わった点のみである演習3:Object型を型変数に指定したリスト操作
import java.util.ArrayList;
import java.util.Iterator;
public class YourClassNameHere {
public static void main(String[] args) {
ArrayList<Object> m = new ArrayList<Object>();
m.add(100);
m.add("hello");
for(Object s : m) {
System.out.println(s);
}
}
}
Objectを指定すると、あらゆるクラスのオブジェクトを格納できるObjectを多用するとプログラムが分かりにくくなるObjectを使用している演習4:ジェネリクスを用いたPairクラスの実装
<クラス名>を指定して、格納するオブジェクトの型を制限する機能class Pair<T>のように記述する。インスタンス生成時に具体的な型を指定する
class Pair<T> {
T s;
T e;
public Pair(T s, T e) {
this.s = s;
this.e = e;
}
public void print() {
System.out.println(s);
System.out.println(e);
}
}
public class YourClassNameHere {
public static void main(String[] args) {
Pair a = new Pair<Integer>(1, 2);
Pair b = new Pair<String>("xx", "yy");
a.print();
b.print();
}
}
sとeは同じ型Tとして宣言されている。インスタンス生成時に指定した型に統一されるnew Pair<Integer>(1, 2)では、sとeがInteger型になるnew Pair<String>("xx", "yy")では、sとeがString型になるまとめ
11. 多相性,インターフェイス,デザインパターン
資料:pi-11. 多相性,インターフェイス,デザインパターン [PDF], [パワーポイント]
起動手順
実行手順
注意点
スーパークラス(親クラス)とサブクラス(子クラス)によるクラス階層を理解し、メソッドのオーバーライド(同名メソッドをクラスごとに異なる内容で再定義すること)を実装する。 前提知識
クラス階層とは、共通する機能を持つ複数のクラスがある場合に、共通部分をスーパークラスにまとめ、個別の機能をサブクラスに定義する構造である。CircleクラスとRectangleクラスはいずれもFigureクラスのサブクラスであり、Figureクラスの機能を継承する。メソッドのオーバーライドにより、areaメソッドがクラスごとに異なる処理を行う。 手順
期待される出力
ヒント
多相性(異なるサブクラスのオブジェクトをスーパークラス型として統一的に扱う仕組み)を理解し、ArrayListを用いた実装を行う。 前提知識
この演習は演習1の発展である。多相性により、CircleオブジェクトもRectangleオブジェクトも「Figureクラスのオブジェクト」として扱える。ArrayList<Figure>に格納すると、各オブジェクトのareaメソッドを呼び出したとき、実際のクラスに応じた計算が行われる。 手順
インターフェイス(クラスが特定のメソッドを実装していることを保証する仕組み)を理解し、継承関係のない複数のクラスで同名メソッドの実装を保証する方法を学ぶ。 前提知識
インターフェイスは、複数のクラスが同名のメソッドを持つことを保証する仕組みである。継承関係がないクラスでも、同じインターフェイスを実装することで、同一種類のオブジェクトとして扱える。インターフェイスに準拠しないクラス定義(必要なメソッドが未実装など)は、コンパイル時に警告が出る。 手順
ソースコード
期待される出力
ヒント
インターフェイスとコレクション(ArrayList)を組み合わせ、異なるクラスのオブジェクトを同一のリストで扱う方法を学ぶ。 前提知識
この演習は演習3の発展である。ArrayList<インターフェイス名>と宣言することで、そのインターフェイスを実装したクラスのオブジェクトを格納できる。これにより、継承関係のないクラスのオブジェクトを同一リストで管理し、共通のメソッドを呼び出せる。 手順
期待される出力
ヒント
この節は発展的な学習項目として紹介する。演習は含まない。 デザインパターンとは、プログラム設計で繰り返し現れる問題とその解決策をまとめたものである。GoF(Gang of Four)の23パターンが知られている。 例として「Template Method」パターンがある。これは、サブクラスごとにメソッドの中身が異なり、スーパークラスではメソッドの中身を書かないというパターンである。演習パート(クリックして展開)
事前準備:Java Tutorの起動と操作
演習1:クラス階層とメソッドのオーバーライド
import java.util.ArrayList;
class Figure {
double x;
double y;
String color;
void move(double dx, double dy) {
x = x + dx;
y = y + dy;
}
double area() {
return 0;
}
}
class Circle extends Figure {
double radius;
double area() {
return radius * radius * 3.14;
}
}
class Rectangle extends Figure {
double width;
double height;
double area() {
return width * height;
}
}
public class Main {
public static void main(String[] args) {
Circle c = new Circle();
c.radius = 3;
c.x = 2;
c.y = 4;
c.color = "green";
Rectangle r = new Rectangle();
r.width = 1;
r.height = 2;
r.x = 6;
r.y = 4;
r.color = "black";
System.out.println(c.area());
System.out.println(r.area());
}
}
28.26
2.0
演習2:多相性
import java.util.ArrayList;
class Figure {
double x;
double y;
String color;
void move(double dx, double dy) {
x = x + dx;
y = y + dy;
}
double area() {
return 0;
}
}
class Circle extends Figure {
double radius;
double area() {
return radius * radius * 3.14;
}
}
class Rectangle extends Figure {
double width;
double height;
double area() {
return width * height;
}
}
public class Main {
public static void main(String[] args) {
ArrayList<Figure> figures = new ArrayList<Figure>();
Circle x = new Circle();
x.radius = 3;
x.x = 2;
x.y = 4;
x.color = "green";
figures.add(x);
Rectangle a = new Rectangle();
a.width = 1;
a.height = 2;
a.x = 6;
a.y = 4;
a.color = "black";
figures.add(a);
for (Figure f : figures) {
System.out.println(f.area());
}
}
}
期待される出力
28.26
2.0
ヒント
演習3:インターフェイス
interface Product {
int total();
}
class Matome implements Product {
int number;
int unit;
public int total() {
return number * unit;
}
}
class Bara implements Product {
int price;
public int total() {
return price;
}
}
public class Main {
public static void main(String[] args) {
Matome m = new Matome();
m.number = 5;
m.unit = 100;
Bara b = new Bara();
b.price = 250;
System.out.println(m.total());
System.out.println(b.total());
}
}
500
250
演習4:インターフェイスとコレクション
import java.util.ArrayList;
interface Product {
int total();
}
class Matome implements Product {
int number;
int unit;
public int total() {
return number * unit;
}
}
class Bara implements Product {
int price;
public int total() {
return price;
}
}
public class Main {
public static void main(String[] args) {
ArrayList<Product> products = new ArrayList<Product>();
Matome m = new Matome();
m.number = 5;
m.unit = 100;
products.add(m);
Bara b = new Bara();
b.price = 250;
products.add(b);
int sum = 0;
for (Product p : products) {
sum = sum + p.total();
}
System.out.println(sum);
}
}
750
補足:デザインパターン
12. 時間,スリープ,疑似乱数,タイマー
資料:pi-12. 時間,スリープ,疑似乱数,タイマー [PDF], [パワーポイント]
起動手順
実行手順
注意点
Javaで現在日時を取得する方法、日時に対する加算計算、およびThread.sleepによる処理の一時停止を習得する。 クラスとオブジェクトの基本を復習しながら、for文とThread.sleepを組み合わせた繰り返し処理を習得する。 ヒント
java.util.Randomクラスを用いて、ランダムな数値を生成する方法を習得する。 ヒント
Threadクラスを継承して複数の処理を並行実行する方法を習得する。シングルスレッドとは単一の処理の流れであり、マルチスレッドとは複数の処理の流れである。本演習では、演習1で学んだThread.sleepを応用しながら、両者の違いを理解する。 ヒント
演習パート(クリックして展開)
事前準備:Java Tutorの起動と操作
演習1:日時に関する計算と処理の一時停止
課題1-1:現在日時の取得
public class Main {
public static void main(String[] args) {
java.time.LocalDateTime d;
d = java.time.LocalDateTime.now();
System.out.println(d);
}
}
課題1-2:日時の加算計算
public class Main {
public static void main(String[] args) {
java.time.LocalDateTime d;
d = java.time.LocalDateTime.now();
System.out.println(d);
System.out.println(d.plusHours(1));
System.out.println(d.plusMinutes(1));
System.out.println(d.plusSeconds(1));
}
}
課題1-3:処理の一時停止
public class Main {
public static void main(String[] args) {
java.time.LocalDateTime d;
d = java.time.LocalDateTime.now();
System.out.println(d);
try {
Thread.sleep(2000);
} catch(InterruptedException e) {}
d = java.time.LocalDateTime.now();
System.out.println(d);
}
}
ヒント
演習2:スリープを用いたオブジェクトの移動
課題2-1:Ballクラスの基本動作確認
class Ball {
double x;
double y;
public Ball(double x, double y) {
this.x = x;
this.y = y;
}
public void move() {
this.x = this.x + 2;
this.y = this.y + 3;
}
public void printout() {
System.out.printf("%f %f\n", this.x, this.y);
}
}
public class Main {
public static void main(String[] args) {
Ball b = new Ball(0, 0);
b.printout();
b.move();
b.printout();
}
}
課題2-2:繰り返しとスリープの組み合わせ
class Ball {
double x;
double y;
public Ball(double x, double y) {
this.x = x;
this.y = y;
}
public void move() {
this.x = this.x + 2;
this.y = this.y + 3;
}
public void printout() {
System.out.printf("%f %f\n", this.x, this.y);
}
}
public class Main {
public static void main(String[] args) {
Ball b = new Ball(0, 0);
b.printout();
for(int i = 1; i <= 10; i++) {
try {
Thread.sleep(1000);
} catch(InterruptedException e) {}
b.move();
b.printout();
}
}
}
演習3:疑似乱数の生成
課題3-1:乱数の生成
public class Main {
public static void main(String[] args) {
int a;
java.util.Random r = new java.util.Random();
a = r.nextInt(10);
System.out.println(a);
}
}
演習4:マルチスレッド
課題4-1:シングルスレッドの動作確認
public class Main {
public static void main(String[] args) {
for(int i = 0; i < 100; i++) {
try {
Thread.sleep(1000);
} catch(InterruptedException e) {}
System.out.println("Hello");
}
}
}
課題4-2:マルチスレッドの基本(1つの別スレッド)
class Morning extends Thread {
public void run() {
for(int i = 0; i < 50; i++) {
try {
Thread.sleep(2000);
} catch(InterruptedException e) {}
System.out.println("Morning");
}
}
}
public class Main {
public static void main(String[] args) {
Morning m = new Morning();
m.start();
}
}
課題4-3:マルチスレッドの拡張(2つの別スレッド)
class Morning extends Thread {
public void run() {
for(int i = 0; i < 50; i++) {
try {
Thread.sleep(2000);
} catch(InterruptedException e) {}
System.out.println("Morning");
}
}
}
class Hello extends Thread {
public void run() {
for(int i = 0; i < 50; i++) {
try {
Thread.sleep(3000);
} catch(InterruptedException e) {}
System.out.println("Hello");
}
}
}
public class Main {
public static void main(String[] args) {
Morning m = new Morning();
m.start();
Hello h = new Hello();
h.start();
}
}
13. 今までの総まとめ
資料:pi-13. 今までの総まとめ [PDF], [パワーポイント]
起動手順
実行手順
注意点
変数を使って複数の類似した式を1つにまとめる「抽象化」の考え方を理解し、メソッドとして定義する方法を習得する。 用語
手順
期待される出力
ヒント
クラスの定義方法と、コンストラクタを用いたオブジェクト生成を理解する。 用語
手順
期待される出力
ヒント
継承の仕組みを理解し、 用語
手順
期待される出力
ヒント
類似した複数のクラスから共通属性を抽出してスーパークラスにまとめる「クラスの抽象化」を理解する。CircleとRectangleという2つのサブクラスを持つクラス階層を実装する。 手順
ソースコード
期待される出力
ヒント
配列とforループを用いた繰り返し処理、および疑似乱数の生成方法を理解する。 用語
手順
期待される出力
注意:浮動小数点数の計算では、わずかな誤差が生じることがある。 ヒント
手順
期待される出力
0から99の範囲の整数が10個出力される。疑似乱数のため、実行するたびに異なる値が出力される。 ヒント
演習パート(クリックして展開)
事前準備:Java Tutorの起動と操作
演習13-1:式の抽象化とメソッド
public class YourClassNameHere {
public static double foo(double a) {
return a * 1.1;
}
public static void main(String[] args) {
System.out.printf("%f\n", foo(100));
System.out.printf("%f\n", foo(150));
System.out.printf("%f\n", foo(400));
}
}110.000000
165.000000
440.000000
fooは、引数aを受け取り、a * 1.1の計算結果を返す100 * 1.1、150 * 1.1、400 * 1.1という3つの類似した式を、変数aを使ってa * 1.1という1つの式にまとめているreturn文はメソッドの戻り値を指定する演習13-2:クラスとコンストラクタ
class Circle {
double x;
double y;
double r;
String color;
public Circle(double x, double y, double r, String color) {
this.x = x;
this.y = y;
this.r = r;
this.color = color;
}
public void printout() {
System.out.printf("%f %f %f %s\n", this.x, this.y, this.r, this.color);
}
}
public class YourClassNameHere {
public static void main(String[] args) {
Circle x = new Circle(2, 4, 3, "green");
Circle y = new Circle(8, 10, 1, "blue");
x.printout();
y.printout();
}
}2.000000 4.000000 3.000000 green
8.000000 10.000000 1.000000 blue
classキーワードでクラスを定義するnewキーワードでコンストラクタを呼び出し、オブジェクトを生成するthisは「メソッドが処理中のオブジェクト自身」を指す。コンストラクタ内でthis.x = x;と書くことで、引数xの値をオブジェクトの属性xに代入する演習13-3:スーパークラス・サブクラス・継承
extendsキーワードを用いたクラスの親子関係の定義方法を習得する。
class Figure {
double x;
double y;
String color;
public Figure(double x, double y, String color) {
this.x = x;
this.y = y;
this.color = color;
}
}
class Circle extends Figure {
double r;
public Circle(double x, double y, double r, String color) {
super(x, y, color);
this.r = r;
}
public void printout() {
System.out.printf("%f %f %f %s\n", this.x, this.y, this.r, this.color);
}
}
public class YourClassNameHere {
public static void main(String[] args) {
Circle x = new Circle(2, 4, 3, "green");
Circle y = new Circle(8, 10, 1, "blue");
x.printout();
y.printout();
}
}2.000000 4.000000 3.000000 green
8.000000 10.000000 1.000000 blue
class Circle extends Figureは「CircleはFigureを継承する」という意味である。Figureがスーパークラス、Circleがサブクラスとなるsuper(x, y, color)はスーパークラスのコンストラクタを呼び出す演習13-4:クラスの抽象化
class Figure {
double x;
double y;
String color;
public Figure(double x, double y, String color) {
this.x = x;
this.y = y;
this.color = color;
}
}
class Circle extends Figure {
double r;
public Circle(double x, double y, double r, String color) {
super(x, y, color);
this.r = r;
}
public void printout() {
System.out.printf("%f %f %f %s\n", this.x, this.y, this.r, this.color);
}
}
class Rectangle extends Figure {
double width;
double height;
public Rectangle(double x, double y, double w, double h, String color) {
super(x, y, color);
this.width = w;
this.height = h;
}
public void printout() {
System.out.printf("%f %f %f %f %s", this.x, this.y, this.width, this.height, this.color);
}
}
public class YourClassNameHere {
public static void main(String[] args) {
Circle x = new Circle(2, 4, 3, "green");
Rectangle a = new Rectangle(6, 4, 1, 2, "blue");
x.printout();
a.printout();
}
}2.000000 4.000000 3.000000 green
6.000000 4.000000 1.000000 2.000000 blue
演習13-5:配列と繰り返し、疑似乱数
演習13-5a:配列と繰り返し
public class YourClassNameHere {
public static void main(String[] args) {
double x[] = {8, 6, 4, 2, 3};
double y[] = {0, 0, 0, 0, 0};
int i;
for(i=0; i<=4; i++) {
y[i] = x[i] * 1.1;
}
for(i=0; i<=4; i++) {
System.out.println(y[i]);
}
}
}8.8
6.6000000000000005
4.4
2.2
3.3000000000000003
x[0]、x[1]のようにインデックス(添字)でアクセスする。インデックスは0から始まるfor(i=0; i<=4; i++)は、iを0から4まで1ずつ増やしながら繰り返す演習13-5b:疑似乱数
import java.util.Random;
public class YourClassNameHere {
public static void main(String[] args) {
Random r = new Random();
int i, a;
for(i=0; i<10; i++) {
a = r.nextInt(100);
System.out.println(a);
}
}
}
import java.util.Random;は標準ライブラリのRandomクラスをインポートする宣言であるr.nextInt(100)は0以上100未満(0から99)の疑似乱数を生成するまとめ
概念 説明 オブジェクト コンピュータでの操作や処理の対象となるもの メソッド オブジェクトに属する操作や処理 クラス 同じ種類のオブジェクトの集まりを定義するもの コンストラクタ オブジェクトの生成を行うメソッド 継承 スーパークラスの属性とメソッドをサブクラスが受け継ぐこと 抽象化 類似した複数の要素から共通部分を抽出してまとめること
14. イベント,イベントハンドラ,ソケット通信
資料:pi-14. イベント,イベントハンドラ,ソケット通信 [PDF], [パワーポイント]
GDB online(https://www.onlinegdb.com)を使用する。オンラインサービスのため、機密性の高いプログラムの取り扱いには注意が必要である。
イベント(event)とは、プログラム実行中に発生する出来事を指す。
代表的な例として、タイマーによる時間経過、キーボードやマウスの操作がある。
イベントハンドラ(event handler)とは、イベント発生時に実行される処理を指す。
プログラムでは、特定のイベントに対して実行すべき処理を事前に登録しておく。
イベントが発生すると、登録された処理が自動的に実行される。
TimerTaskクラスを用いて、一定時間ごとに処理を実行するプログラムを作成する。
使用環境
この演習ではGDB online(https://www.onlinegdb.com)を使用する。
タイマーイベントのプログラムでは、メインの処理を一定時間待機させる必要がある。
待機させないと、メインの処理が終了した時点でプログラム全体が終了し、タイマーイベントが発生しなくなるためである。
ここでは、Thread.sleepメソッドを用いた処理の一時停止を確認する。
手順
ヒント
Thread.sleepメソッドの引数はミリ秒単位である。100000ミリ秒は100秒に相当する。
try-catch文で囲んでいるのは、Thread.sleepがInterruptedException(割り込み例外)をスローする可能性があるためである。
手順
ヒント
TimerTaskはJava標準ライブラリのクラスで、タイマーイベントのイベントハンドラを定義するために使用する。
MyTaskクラスはTimerTaskを継承し、runメソッドにイベント発生時の処理を記述する。
timer.schedule(new MyTask(), 100, 500)の各引数の意味は以下のとおりである。
第1引数は実行するタスク、第2引数は最初のイベント発生までの待機時間(ミリ秒)、第3引数はその後のイベント発生間隔(ミリ秒)である。
この例では、0.1秒後に最初のイベントが発生し、その後0.5秒間隔でイベントが発生する。
タイマーイベントはメインの処理とは別のスレッド(実行の流れ)で動作する。
これをマルチスレッド実行と呼ぶ。
メインの処理がThread.sleepで待機している間も、タイマーイベントは別スレッドで定期的に実行される。
クラスとタイマーイベントを組み合わせ、オブジェクトの状態を定期的に更新するプログラムを作成する。
Ballクラスの説明
この演習で使用するBallクラスは、x座標とy座標を属性として持つ。
moveメソッドは、x座標の値を2増やし、y座標の値を3増やす。
printoutメソッドは、現在の座標を表示する。
手順
ヒント
実行結果は以下のようになる。
1行目は初期座標「0.000000 0.000000」、2行目はmoveメソッド呼び出し後の座標「2.000000 3.000000」である。
手順
ヒント
MyTaskクラスのコンストラクタでBallオブジェクトを生成し、runメソッド内でmoveとprintoutを呼び出している。
0.5秒ごとにイベントが発生し、そのたびにBallの座標が更新されて表示される。
ソケット(socket)は、機器間の通信やプロセス間通信に使用するインターフェースである。
インターネット通信では、サーバ(要求を待ち受ける側)とクライアント(要求を送る側)が存在する。
サーバ側では、実行中のプログラムがサーバソケットにバインド(bind:結び付け)される。
サーバソケットには特定のポート番号が割り当てられる。
サーバは接続要求が来るのを待つ。これをaccept(受け入れ)と呼ぶ。
クライアント側では、サーバのIPアドレス(またはサイト名)とポート番号を指定して通信を開始する。
サーバソケットは接続要求を待ち受けるためのソケットである。
データ送受信用ソケットは、実際のデータのやり取りに使用するソケットで、サーバソケットとは別のものである。
HTTP(Hypertext Transfer Protocol)は、WebブラウザとWebサーバ間の通信に使用するプロトコルである。
クライアントがリクエスト(要求)を送信し、サーバがレスポンス(応答)を返す形式で通信が行われる。
HTTPの標準ポート番号は80である。
Javaでソケット通信を行い、Webサーバからデータを取得するプログラムの動作を確認する。
使用環境
この演習ではpaiza.io(https://paiza.io/)を使用する。
手順
ヒント
Socket s = new Socket("www.kkaneko.jp", 80)で、サーバのサイト名とポート番号を指定して接続を確立する。
BufferedReaderはデータ受信用、BufferedWriterはデータ送信用のクラスである。
InputStreamReaderとOutputStreamWriterは、バイト列と文字列を相互に変換するためのクラスである。
getInputStreamメソッドで受信用のストリーム(データの流れ)を、getOutputStreamメソッドで送信用のストリームを取得する。
out.writeでHTTPリクエストを送信している。
HTTP/1.0では、リクエストの終わりを空行(\r\n)で示す。
out.flushは、バッファ(一時的な保存領域)に蓄積されたデータを実際に送信するためのメソッドである。
in.readLineで、サーバからのレスポンスを1行ずつ読み取る。
イベントとイベントハンドラについては、イベント発生時に実行する処理を事前に登録する仕組みを学んだ。
TimerTaskクラスを用いることで、定期的な処理をマルチスレッドで実行できる。
ソケット通信については、ソケットを用いてインターネット経由でデータを送受信する方法を学んだ。
サーバ側ではプログラムをサーバソケットにバインドし、クライアント側ではサーバのIPアドレス(またはサイト名)とポート番号を指定して通信を開始する。
演習パート(クリックして展開)
使用するオンライン環境
GDB onlineの基本操作
イベントとは
イベントハンドラとは
演習1:タイマーイベント(基礎)
演習1-1:処理の一時停止
import java.util.*;
public class Main {
public static void main(String[] args) {
System.out.println("start");
try {
Thread.sleep(100000);
} catch(InterruptedException e) {}
}
}
演習1-2:タイマーイベントの実装
import java.util.*;
class MyTask extends TimerTask {
public void run() {
System.out.println("hello");
}
}
public class Main {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new MyTask(), 100, 500);
System.out.println("start");
try {
Thread.sleep(100000);
} catch(InterruptedException e) {}
}
}
演習2:タイマーイベント(応用)
演習2-1:Ballクラスの動作確認
class Ball {
double x;
double y;
public Ball(double x, double y) {
this.x = x;
this.y = y;
}
public void move() {
this.x = this.x + 2;
this.y = this.y + 3;
}
public void printout() {
System.out.printf("%f %f\n", this.x, this.y);
}
}
public class Main {
public static void main(String[] args) {
Ball b = new Ball(0, 0);
b.printout();
b.move();
b.printout();
}
}
演習2-2:タイマーイベントによる定期的な移動
import java.util.*;
class Ball {
double x;
double y;
public Ball(double x, double y) {
this.x = x;
this.y = y;
}
public void move() {
this.x = this.x + 2;
this.y = this.y + 3;
}
public void printout() {
System.out.printf("%f %f\n", this.x, this.y);
}
}
class MyTask extends TimerTask {
Ball b;
public MyTask() {
super();
this.b = new Ball(0, 0);
}
public void run() {
b.move();
b.printout();
}
}
public class Main {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new MyTask(), 100, 500);
System.out.println("start");
try {
Thread.sleep(100000);
} catch(InterruptedException e) {}
}
}
ソケットとは
インターネット通信の仕組み
サーバソケットとデータ送受信用ソケット
HTTPプロトコルの基本
演習3:ソケット通信
import java.util.*;
import java.net.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
try {
Socket s = new Socket("www.kkaneko.jp", 80);
BufferedReader in = new BufferedReader
(new InputStreamReader(s.getInputStream()));
BufferedWriter out = new BufferedWriter
(new OutputStreamWriter(s.getOutputStream()));
out.write("GET /index.html HTTP/1.0\r\n");
out.write("Host: www.kkaneko.jp:80\r\n");
out.write("\r\n");
out.flush();
System.out.println(in.readLine());
System.out.println(in.readLine());
System.out.println(in.readLine());
System.out.println(in.readLine());
} catch(Exception e) {
e.printStackTrace();
}
}
}
まとめ
15. カプセル化,MVCモデル,オブジェクトのマッピング
資料:pi-15. カプセル化,MVCモデル,オブジェクトのマッピング [PDF], [パワーポイント]
GDB online(https://www.onlinegdb.com)を使用する。オンラインサービスのため、機密性の高いプログラムの取り扱いには注意が必要である。 カプセル化(encapsulation)とは、オブジェクトが持つ属性とメソッドのうち、必要なもののみを他のオブジェクトに公開する仕組みである。外部から直接変更されたくないデータを保護し、オブジェクトの内部構造を隠蔽できる。Java では public(公開)と private(非公開)の指定により、属性やメソッドへのアクセス制御を行う。 MVC モデルとは、プログラムを以下の3つの要素に分離して設計する手法である。 この分離により、プログラムの見通しが良くなる。 MVC モデルにおけるモデル部分(Person クラス、Meibo クラス)とコントローラー部分(Main クラス)を実装し、クラス間の連携を理解する。 手順
ヒント
演習1の課題
現在の実装では、モデルが直接出力を担当している。このため、表示形式を変更するにはモデルのコードを修正する必要がある。また、モデル内のすべてのデータ(ID を含む)が出力されており、一部のデータのみを表示したい場合に対応しにくい。演習2では、ビューを導入してこの課題を解決する。 View クラスを追加し、モデルとビューを分離した設計を体験する。 手順
ソースコード
ヒント
演習で学んだ MVC モデルは、実際の開発でどのように活用されるか。ここでは2つの応用を紹介する。 Java オブジェクトは、リレーショナルデータベースや DOM オブジェクト(Document Object Model:文書をノードの階層構造として表現するモデル)にマッピング(対応付け)できる。これにより、データベースの検索結果を Java オブジェクトとして扱ったり、Web ブラウザでの表示を動的に変更したりできる。 Java には MVC モデルに適したフレームワーク(アプリケーションの土台となるソフトウェア)が多数ある。代表的なものとして Struts、JSF(Java Server Faces)、Spring Framework がある。これらを使用すると、Web アプリケーションを効率的に開発できる。演習パート(クリックして展開)
使用するオンライン環境
GDB onlineの基本操作
カプセル化
MVC モデル
演習1:MVC モデルの実装(ビューなし)
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
class Person {
String name;
String address;
public Person(String name, String address) {
this.name = name;
this.address = address;
}
public void printout() {
System.out.printf("%s %s\n", this.name, this.address);
}
}
class Meibo {
HashMap<Integer, Person> m;
public Meibo(HashMap<Integer, Person> m) {
this.m = m;
}
public void add(int id, String name, String address) {
m.put(id, new Person(name, address));
}
public void printout() {
for(Integer i : this.m.keySet()) {
System.out.printf("%d, ", i);
this.m.get(i).printout();
}
}
}
public class Main {
public static void main(String[] args) throws Exception {
HashMap<Integer, Person> m = new HashMap<Integer, Person>();
Meibo a = new Meibo(m);
a.add(1, "XX", "Fukuyama");
a.add(2, "YY", "Okayama");
a.printout();
}
}
演習2:MVC モデルの実装(ビューあり)
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
class Person {
String name;
String address;
public Person(String name, String address) {
this.name = name;
this.address = address;
}
public void printout() {
System.out.printf("%s %s\n", this.name, this.address);
}
}
class Meibo {
HashMap<Integer, Person> m;
public Meibo(HashMap<Integer, Person> m) {
this.m = m;
}
public void add(int id, String name, String address) {
m.put(id, new Person(name, address));
}
public void printout() {
for(Integer i : this.m.keySet()) {
System.out.printf("%d, ", i);
this.m.get(i).printout();
}
}
}
class View {
ArrayList<Person> v;
public View() {
}
public void update(Meibo meibo) {
this.v = new ArrayList<Person>();
for(Integer i: meibo.m.keySet()) {
v.add(meibo.m.get(i));
}
}
public void printout() {
for(Person p: this.v) {
System.out.printf("%s %s\n", p.name, p.address);
}
}
}
public class Main {
public static void main(String[] args) throws Exception {
HashMap<Integer, Person> m = new HashMap<Integer, Person>();
Meibo a = new Meibo(m);
a.add(1, "XX", "Fukuyama");
a.add(2, "YY", "Okayama");
View v = new View();
v.update(a);
v.printout();
}
}
発展学習
オブジェクトのマッピング
MVC モデルに対応するフレームワーク
16. プログラムのテスト,アサーション,例外処理
資料:pi-16. プログラムのテスト,アサーション,例外処理 [PDF], [パワーポイント]
GDB online(https://www.onlinegdb.com)を使用する。オンラインサービスのため、機密性の高いプログラムの取り扱いには注意が必要である。 プログラム設計レシピは、プログラムを設計するときに考えておくべきこと、実行すべきことをまとめたものである。次の4段階で構成される。 メソッドに名前を付け、入力と出力を明らかにする。 メソッドの性能や機能の条件を定める。 どのような入力に対して、どのような出力が得られるべきかを具体的に示す。例があることで、プログラムが書きやすくなり、他者がプログラムを理解しやすくなる。また、テストの実施にも利用できる。 プログラムが設計どおりに動作するかを確認する。 Ringクラスを作成し、areaメソッドでリングの面積を計算する。設計レシピの4段階を実践する。 リングは外径r2と内径r1を持つドーナツ状の図形である。面積は次の式で計算する。 プログラムを実行して動作を観察する。 言語の書式に合っていない場合に発生する。プログラムを実行しようとすると、実行できずにエラーメッセージが表示される。例えば、スペルミスや括弧の不足がこれに該当する。 プログラムの実行中に発生し、出力が得られない。実行するとエラーメッセージが表示されたり、プログラムが停止したように見えたりする。 プログラムは実行できるが、出力が仕様に合致しない。プログラムを実行してテストすることで発見する。 次のプログラムには実行エラーが含まれている。どこに問題があるか考えてから実行し、確認すること。 アサーションは「必ず成立しているはずのこと」を記述したものである。論理的エラーの発見に役立つ。 この例では「x >= 0」がアサーションである。この条件が成立しない場合、「error, x < 0 in area()」というメッセージが表示される。 アサーションの機能はGDB onlineで動作させることが難しい。 例外処理は、不測の事態に対応するための仕組みである。 メソッド内で例外が発生する可能性があることを宣言する。 例外を発生させる。 tryブロック内で例外が発生した場合、catchブロック内の例外処理が実行される。 この章で学んだ内容は次のとおりである。演習パート(クリックして展開)
使用するオンライン環境
GDB onlineの基本操作
プログラム設計レシピ
第1段階:分析
第2段階:仕様
第3段階:例
第4段階:テスト
演習:リングの面積プログラム
目的
リングの面積
(r2 * r2 - r1 * r1) * 3.14設計レシピの適用
段階 内容 分析 メソッド名:area、入力:なし(属性r1, r2を使用)、出力:数値1つ(面積) 仕様 r1を内径、r2を外径とするリングの面積を求める 例 r1 = 3、r2 = 5のとき、50.24が求まる テスト プログラムを実行し、期待どおりの結果が得られることを確認する 手順
class Ring {
double r1;
double r2;
public Ring(double r1, double r2) {
this.r1 = r1;
this.r2 = r2;
}
public double area() {
double x;
x = (this.r2 * this.r2 - this.r1 * this.r1) * 3.14;
return x;
}
}
public class Main {
public static void main(String[] args) {
Ring a = new Ring(3, 5);
System.out.println(a.area());
}
}
確認ポイント
2. エラーの種類とテスト
構文エラー
実行エラー
論理的エラー
観察:実行エラーを含むプログラム
class Ring {
double r1;
double r2;
public Ring(double r1, double r2) {
this.r1 = r1;
this.r2 = r2;
}
public double area() {
double x;
x = (this.r2 * this.r2 - this.r1 * this.r1) / 0;
return x;
}
}
public class Main {
public static void main(String[] args) {
Ring a = new Ring(3, 5);
System.out.println(a.area());
}
}
観察のポイント
アサーションとは
Javaでの記述方法
assert x >= 0 : "error, x < 0 in area()";注意
例外処理とは
不測の事態の例
Javaでの記述方法
throws Exception
throw new Exception
try-catch構文
try {
処理
} catch(Exception e) {
例外処理
}
学習のまとめ
17. プログラム設計
資料:pi-17. プログラム設計 [PDF], [パワーポイント]
Javaでは、クラスを定義し、クラス間に継承関係を設けることで、コードの再利用性を高められる。UMLクラス図は、このようなクラス構造を設計段階で視覚的に表現する手法である。本節では、演習に必要な概念を確認する。 クラス定義には、属性の定義(属性名とデータ型)、コンストラクタの定義、メソッドの定義を含める。コンストラクタとは、オブジェクトを生成するためのメソッドである。 クラス階層とは、複数のクラスが親子関係を形成することである。継承とは、親クラス(スーパークラス)の属性とメソッドを子クラス(サブクラス)が受け継ぐ仕組みである。継承により、共通する属性やメソッドを親クラスにまとめ、子クラスでは差分のみを定義できる。 UML(Unified Modeling Language)のクラス図は、プログラムの設計図の記法の一つである。クラス図には、クラスの属性、操作、クラス間の相互関係を記述する。 クラス間の相互関係には以下の2種類がある。 draw.ioを使用してUMLクラス図を作成する。この演習を通じて、クラスの属性と操作の記述方法、および親子関係の表現方法を身につける。 使用ツール
draw.io:チャートや設計図を作成できるオンラインサービスである。 URL: https://www.draw.io 課題
以下の仕様に従い、3つのクラスとその親子関係を表すクラス図を作成しなさい。 注意事項
UMLクラス図では、子クラスには親クラスから継承する属性や操作を記載しない。子クラス固有の属性と操作のみを記載する。 手順
ヒント
UMLクラス図に基づいてJavaプログラムを作成する。この演習を通じて、クラス定義、継承、関連をJavaで実装する方法を身につける。 使用ツール
GDB online:Javaなどのプログラミング言語を実行できるオンラインサービスである。 URL: https://www.onlinegdb.com 注意:オンラインサービスであるため、機密性の高いプログラムを扱う際は注意が必要である。 課題
以下の仕様に従い、3つのクラスを定義し、動作を確認しなさい。 PersonクラスはAddressクラスと関連を持つ。これは、PersonクラスがAddress型の属性を持つことで実装する。関連の多重度は、Person側が1、Address側が0..1である(1人のPersonに対してAddressは0個または1個)。 手順
ヒント
よくある間違い
期待される実行結果
演習パート(クリックして展開)
重要概念
クラス定義
クラス階層と継承
UMLクラス図
演習1:UMLクラス図の作成
クラス名 親クラス 属性 操作 Ball なし x, y, color move, reset Circle Ball r (継承のみ) Rectangle Ball w, h (継承のみ)
演習2:UMLクラス図からJavaプログラム作成
クラス名 親クラス 属性 操作 Address なし address print Person なし name, a(Address型) print Student Person id print
class Address {
String address;
public Address(String address) {
this.address = address;
}
public void print() {
System.out.println(this.address);
}
}
class Person {
String name;
Address a;
public Person(String name, Address a) {
this.name = name;
this.a = a;
}
public void print() {
System.out.println(this.name);
this.a.print();
}
}
class Student extends Person {
int id;
public Student(String name, Address a, int id) {
super(name, a);
this.id = id;
}
public void print() {
System.out.println(this.name);
System.out.println(this.id);
this.a.print();
}
}
public class Main {
public static void main(String[] args) {
Address a = new Address("Fukuoka");
Student s = new Student("kaneko", a, 10);
s.print();
}
}
extendsキーワードは継承を表す。class Student extends Personは、StudentクラスがPersonクラスを継承することを意味するsuper(name, a)は親クラス(Person)のコンストラクタを呼び出す
extendsの綴り間違いsuper()の呼び出し忘れ(子クラスのコンストラクタでは、親クラスのコンストラクタを呼び出す必要がある)kaneko
10
Fukuoka