Java 学習教材（２）筑波⼤学 システム情報系 三⾕純
最終更新⽇ 2023/4/19(C) 2023 Jun Mitani

図表出典：三⾕純著『プログラミング学習シリーズ Java』（翔泳社 刊）

本資料の位置づけ
本資料は『Java 第3版実践編
アプリケーション作りの基本』

Java 第3版 実践編
アプリケーション作りの基本（三⾕純 著）を専⾨学校・⼤学・企業などで教科書として採⽤された教員・指導員を対象に、教科書の内容を解説するための副教材として作られています。
上記に該当する場合は、⾃由にご使⽤ください。授業の進め⽅などに応じて、改変していただいて結構です。※ このページを削除して構いません
ただし、⺠間企業が商⽤、ビジネス⽬的で利⽤する際には別途許諾が必要ですので、著者までご連絡ください。

出版社： 翔泳社
発売⽇： 2021/1/18
ISBN ： 9784798167077

第1章 パッケージとJava API

モジュールとパッケージ• Javaには「クラスライブラリ」と呼ばれる、便利なクラスやインタフェースが準備されている• クラスライブラリは必要に応じて⾃由に使える• クラスライブラリは「モジュール」と「パッケージ」で管理されている

Javaの主なモジュールとパッケージパッケージに含まれるクラスの利⽤
java.utilパッケージに含まれるRandomクラスのインスタンスを⽣成する例
java.util.Random rand = new java.util.Rondom();
パッケージ名クラス名（パッケージ名）.（クラス名）という表現をクラスの完全限定名というimport宣⾔
完全限定名を毎回記述するのは⼤変
とても⻑い完全限定名の例

javax.xml.bind.annotation.adapters.XmlAdapter
パッケージ名

クラス名

import宣⾔をすれば、プログラムの中でパッケー
ジ名の記述を省略できる
import パッケージ名.クラス名;

import宣⾔の効果

import宣⾔の使⽤例
import java.util.Random;
public class ImportExample {public static void main(String[] args) {Random rand = new Random();// 0～1の間のランダムな値を出力する
System.out.println(rand.nextDouble());}}

java.util.Random のimport宣⾔をしている

複数のクラスのimport宣⾔• 複数のクラスをimport宣⾔する場合、そのクラスの数だけ宣⾔する
import java.util.ArrayList;
import java.util.Random;*（アスタリスク）記号を使って省略できる
import java.util.*;java.utilパッケージに含まれる全てのクラスを
import宣⾔したのと同じ

パッケージの階層
例えば次の⼆つは異なるパッケージ
java.utilパッケージ
java.util.zipパッケージ
import java.util.*;と記述してもjava.util.zipパッケージのクラスは使⽤できない
次のように記述する
import java.util.*;import java.util.zip.*;java.langパッケージ• java.langパッケージにはJavaの基本的な機能を提供するクラスが含まれる• 「System.out.println()」のSystem
クラスもjava.langパッケージに含まれる• 「import java.lang.*;」という記述は省略できる

API仕様書
Javaにはあらかじめ膨⼤な数のクラスやインタフェースが準備されているAPI仕様書で使い方を調べられる
http://docs.oracle.com/javase/jp/11/docs/api/※ バージョンが異なる場合は⾚字部分を変更

API仕様書で確認できるクラス情報• Randomクラスはjava.baseモ
ジュールのjava.utilパッケージに含まれる• java.lang.Objectクラスを継承している• Serializableインタフェースを実装
している• サブクラスにSecureRandomクラスとThreadLocalRandomクラスがある

クラスの情報・クラスの説明・フィールドの説明
・コンストラクタの説明
・メソッドの説明

Stringクラス• String は java.langパッケージに含まれる
クラス• 次の2通りでインスタンスを⽣成できる
String message = "こんにちは";String message = new String("こんにちは");

new を使わなくてもインスタンスを作れる特殊なクラス

Stringオブジェクトの⽣成⽅法による違い
String s1 = new String("こんにちは");
String s2 = new String("こんにちは");
System.out.println(s1 == s2); // false

異なる2つのインスタンスが⽣成される
たまたま⽂字列が同じだけ

Stringオブジェクトの⽣成⽅法による違い
String s1 = "こんにちは";String s2 = "こんにちは";
System.out.println(s1 == s2); // true

1つのインスタンスを参照する

Stringクラスのメソッド
Stringクラスには、⽂字列を扱うための便利なメソッドがある
String str = "Javaの学習";
System.out.println(str.length()); // 7
System.out.println(str.indexOf("学習")); // 5
System.out.println(str.indexOf("Ruby")); // -1
System.out.println(str.contains("学習")); // true
System.out.println(str.contains("Ruby")); // false
String str2 = str.replace("Java", "Java言語"));
System.out.println(str2); // Java言語の学習

Stringクラスのメソッド
文字列を区切り記号で分割する例

String str = "2020/11/22";
String[] items = str.split("/");
for(int i = 0; i < items.length; i++) {System.out.println(items[i]);
}
実行結果

2020
11
22

Mathクラス
java.lang.Mathクラスには数学的な計算を⾏う便利なクラスメソッドが多数ある

Mathクラスの使⽤• java.langパッケージはimport⽂を省略できる• クラスメソッドの使⽤⽅法（復習）「Math.メソッド名(引数);」
class MathExample {public static void main(String[] args) {System.out.println("-5の絶対値は" + Math.abs(-5));
System.out.println("3.0の平方根は" + Math.sqrt(3.0));
System.out.println("半径2の円の面積は" + 2*2*Math.PI);
System.out.println("sin60°は" +Math.sin(60.0*Math.PI / 180.0));}}パッケージの作成
パッケージは⾃分で作成できる。
package パッケージ名;とプログラムコードの先頭に記述する。
package mypackage;
public class MyClass {public void printMessage() {System.out.println("mypackage.MyClassのprintMessageメソッド");}}
Eclipseでは[ファイル]-[新規]-[パッケージ]でパッケージを新規作成。
その中にクラスを作成する。

パッケージの階層構造とフォルダの階層構造
jp.co.javacompany.developパッケージ内に
MyClassクラスがある場合

注：クラスの継承の階層とパッケージの階層は関係ないパッケージ名の設定• パッケージ名は他⼈が作ったものと同じものではいけない（名前の衝突）• ドメイン名をパッケージ名に使⽤することが多い。並び順は逆。
例：jp.co.javacompany.develop

クラスのアクセス制御
アクセス修飾⼦を使って、パッケージ外部
からのアクセスを制御できるクラスとインタフェースの宣言で使用できるアクセス修飾子

メソッドとフィールドのアクセス修飾⼦
メソッドとフィールドの宣⾔で使⽤できるアクセス修飾⼦

アクセス修飾⼦の優先順位
フィールドやメソッドのアクセス修飾⼦がpublicであっても、クラスのアクセス修飾⼦がpublicでない場合は、パッケージの外からはアクセスできない複数のクラス宣⾔を持つプログラムコード• 1つの.javaファイルで複数のクラスを宣⾔できる• public修飾⼦をつけられるのは1つだけ• public修飾⼦をつけたクラス名とファイル名は⼀致する必要がある
MultiClassExample.javaclass SimpleClass {String str;
SimpleClass(String str) {this.str = str;}}
public class MultiClassExample {public static void main(String[] args) {SimpleClass sc = new SimpleClass("Hello.");System.out.println(sc.str);}}

第2章 例外処理

例外の発⽣• プログラムが動作する時にトラブルが発⽣することがある。これを「例外」と⾔う「例外が発⽣する」「例外が投げられる」「例外がスロー(throw)される」などと表現する

例外が発⽣する例
ゼロでの除算int a = 4;
int b = 0;
System.out.println(a / b);例外が発⽣する例
範囲を超えたインデックスの参照
int[] scores = new int[3];scores[0] = 50;scores[1] = 55;scores[2] = 70;
scores[3] = 65;

投げられた例外をキャッチする• 例外が投げられたときにも、その例外をキャッチして処理を続けることができる仕組みがある• try〜catch⽂を使う• 「例外処理」と呼ぶ

try〜catch⽂try {tryブロック
本来実⾏したい処理だが、例外が投げられる可能性がある処理}
catch(例外の型 変数名) {catchブロック
例外が投げられたときの処理}
finally {finallyブロック
最後に必ず⾏う処理}

処理の流れ例外処理の例
public class ExceptionExample3 {public static void main(String[] args) {int a = 4;
int b = 0;
try {int c = a / b;
System.out.println("cの値は" + c);}
catch (ArithmeticException e) {System.out.println("例外をキャッチしました");
System.out.println(e);}System.out.println("プログラムを終了します");}}finallyの処理
public static void main(String[] args) {int a = 4;
int b = 0;
try {int c = a / b;
System.out.println("cの値は" + c);}
catch (ArithmeticException e) {System.out.println("例外をキャッチしました");
System.out.println(e);return;}finally {System.out.println("finallyブロックの処理です");}
System.out.println("プログラムを終了します");}catchブロックの検索
class SimpleClass {void doSomething() {int array[] = new int[3];array[10] = 99; // 例外が発生する
System.out.println("doSomethingメソッドを終了します");}}public class ExceptionExample5 {public static void main(String args[]) {SimpleClass obj = new SimpleClass();try {obj.doSomething(); // 例外の発生するメソッドの呼び出し}
catch (ArrayIndexOutOfBoundsException e) {System.out.println("例外をキャッチしました");
e.printStackTrace();}}}例外オブジェクト• 例外が発⽣した時にはjava.lang.Exceptionクラスの「例外オブジェクト」が投げられる• 実際は、Exceptionクラスのサブクラス• 例外の種類によって異なる
ゼロ除算：ArithmeticException
配列の範囲を超えた参照
ArrayIndexOutOfBoundsException例外オブジェクトの種類による場合分けtry {例外が投げられる可能性のある処理}
catch(例外の型1 変数名1) {例外の型1の例外が投げられたときの処理}
catch(例外の型2 変数名2) {例外の型2の例外が投げられたときの処理}
finally {最後に必ず⾏う処理}

例外クラスの階層

Exceptionオブジェクトが投げられる可能性がある場合はtry〜catch⽂を書かなくてはいけない。
ただし、RuntimeExceptionだけは、try〜catch⽂が無くてもよい。

例外を作成して投げる• 例外オブジェクトを⾃分で作成して投げることができる• 例外オブジェクトの作成
Exception e = new Exception("○○という例外が発生しました");• 例外オブジェクトを投げる
throw e;
※通常はExceptionクラスをそのまま使⽤せず、サブクラスを作って例外を投げる。

メソッドの外への例外の送出
⾃分で作成した例外オブジェクトをthrowした後の処理
1. try〜catch⽂で囲んで処理する
2. メソッドの外に投げる（メソッドの呼び出し側で処理する）
2の場合はメソッドの宣⾔に throws を追加する

戻り値 メソッド名(引数) throws 例外の型 {例外を投げる可能性のあるメソッドの内容}

メソッドの外への例外の送出の例
class Person {int age;void setAge(int age) throws InvalidAgeException {if(age < 0) {throw new InvalidAgeException("マイナスの値が指定された");}
this.age = age;}}
public class ExceptionExample7 {public static void main(String[] args) {Person p = new Person();try {p.setAge(-5);} catch (InvalidAgeException e) {System.out.println(e);}}}第3章 スレッド

スレッドとは• スレッドは処理の流れ• これまで⾒てきたプログラムは命令が1つずつ処理された ←シングルスレッド• Javaでは複数の処理を同時に⾏うことができる ← マルチスレッド
例1.ファイルをダウンロードしながら画⾯の表⽰を更新する
例2.アニメーション表⽰しながらユーザのマウス操作を受け付けるスレッドの作成• 通常のプログラムは1つのスレッドで実⾏される• 新しいスレッドを追加できる• 次の2つの⽅法がある
1. Threadクラスを継承した新しいクラスを作成する
2. Runnableインタフェースを実装した新しいクラスを作成する

⽅法1. Threadクラスを拡張する
class MyThread extends Thread {// Thread クラスのrunメソッドをオーバーライド

public void run() {命令文}}• Threadクラスを継承したクラスを作成する• runメソッドをオーバーライドする• 「命令⽂」に処理を記述する

⽅法1のThreadの使⽤例
class MyThread extends Thread {public void run() {for(int i = 0; i < 100; i++) {System.out.println("MyThreadのrunメソッド("+i+")");}}}
public class SimpleThreadTest {public static void main(String[] args) {MyThread t = new MyThread();t.start();for(int i = 0; i < 100; i++) {System.out.println("SimpleThreadTestのmainメソッド("+i+")");}}}

Threadの使⽤例• Threadクラスのrunメソッドを直接呼ばない• startメソッドを呼ぶことで、別スレッドの処理が始まる• 複数のスレッドが並⾏して処理を進める

⽅法2. Runnableインタフェースを実装する
⽅法1がいつでも使えるとは限らない。
例：他のクラスのサブクラスは、Threadク
ラスのサブクラスになれない
⽅法2
・Runnableインタフェースを実装する
・Runnableインタフェースに定義されている
runメソッドを追加する

⽅法2のThread使⽤例
class MyThread implements Runnable {public void run() {for(int i = 0; i < 100; i++) {System.out.println("MyThreadのrunメソッド("+i+")");}}}
public class SimpleThreadTest2 {public static void main(String[] args) {MyThread t = new MyThread();Thread thread = new Thread(t);thread.start();for(int i = 0; i < 100; i++) {System.out.println("SimpleThreadTest2のmainメソッド("+i+")");}}}

スレッドを⼀定時間停⽌させる
Thread.sleep(停止時間（ミリ秒）);
public class SleepExample {public static void main(String[] args) {for(int i = 0; i < 10; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {System.out.println(e);}System.out.print("*");}}}

スレッドの終了を待つ
スレッドAからスレッドBのjoinメソッドを呼ぶと、スレッドBの処理が終わるまでスレッドAは次の処理に移らない。

MyThread t = new MyThread();t.start();try{
t.join();} catch (InterruptedException e) {System.out.println(e);}joinメソッドの呼び出しによる待機スレッドを⽌める• スレッドはrunメソッドの処理が終了すると、動作が⽌まる• whileループの条件を制御してrunメソッドを終了させるのが⼀般的
class MyThread extends Thread {public boolean running = true;
public void run() {while(running) {// 命令文}System.out.println("runメソッドを終了");}}

マルチスレッドで問題が⽣じるケース• 複数のスレッドが1つの変数に同時にアクセスすると、不整合が⽣じる場合がある• スレッドAが変数iの値を1増やす• スレッドBが変数iの値を1増やす• 上記の処理が同時に⾏われるとiの値が1しか増えない場合がある

問題が⽣じないケース
変数moneyの値（現在の値は98）をスレッドAとスレッドBが1ずつ増やす処理

問題が⽣じるケース
変数moneyの値（現在の値は98）をスレッドAとスレッドBが1ずつ増やす処理。スレッドAの処理にスレッドBが割り込んだ

スレッドの同期
メソッドにsynchronized修飾⼦をつけると、そのメソッドを実⾏できるスレッドは⼀度に1つに限定される
static synchronized void addOneYen() {money++;}
あるスレッドによってメソッドが実⾏されている間は、他のスレッドはその処理が終わるまで待機することになる。
これをスレッドの同期と呼ぶ

第4章 ガーベッジコレクションとメモリ

プログラムの実⾏とメモリ管理• プログラム実⾏中に覚えておかなくてはならな
い情報はメモリに格納される。
• メモリにはスタックとヒープと呼ばれる領域がある。
・メソッドの呼び出し履歴・メソッドの中で宣⾔されたローカル変数の値
スタック ・メソッドの処理が終わると、そのメソッドに関する情報と変数が削除される

ヒープ

・⽣成されたインスタンス
・ガーベッジコレクタによって管理される

スタックとヒープ
MyObject doSomething() {MyObject obj = new MyObject();
return obj;}

空きメモリサイズの確認
class DataSet {int x;
int y;}
public class FreeMemoryTest {public static void main(String[] args) {System.out.println("空きメモリサイズ:" +Runtime.getRuntime().freeMemory());
DataSet[] data = new DataSet[100];for(int i = 0; i < 100; i++) {data[i] = new DataSet();
System.out.println("生成済みインスタンス数:" + (i + 1) +" 空きメモリサイズ:" +Runtime.getRuntime().freeMemory());}}}

使⽤できるサイズは有限• インスタンスを⼤量に⽣成すると、ヒープを消費する。全て使い切ってしまうと実⾏時エラーが発⽣する。
• メソッドの呼び出しの階層があまりに深いとスタックも使いきる可能性がある（再帰呼び出しなどを⾏った場合）

ガーベッジコレクション• プログラムの中で不要になったインスタ
ンスの情報を削除し、メモリの空き領域を増やす処理• Java仮想マシンが⾃動で⾏う
インスタンスが不要になる

インスタンスがどこからも参照されなくなるガーベッジコレクションの対象になるタイミング
MyObject obj1 = new MyObject();
MyObject obj2 = new MyObject();

obj2 = obj1;

参照先の変更ガーベッジコレクションの対象

ガーベッジコレクションの対象になるタイミング
MyObject obj = new MyObject();
obj = null;
nullの代⼊⽣成されたインスタンスは誰からも参照されなくなる

void doSomething() {MyObject obj = new MyObject();}
メソッドの処理が終わると、⽣成されたインスタンスは誰からも参照されなくなる。

ガーベッジコレクションが実⾏されるタイミング• Java仮想マシンが適切なタイミングで実⾏する• ガーベッジコレクションは時間のかかる処理なので、ある程度不要なインスタンスが貯まってからまとめて⾏われる• Runtime.getRuntime().gc();
または
System.gc();の命令⽂で、ガーベッジコレクションを指定したタイミングで⾏わせることもできる

第5章 コレクション

⼤きさの変わる配列
Javaでの配列の使い⽅
MyObject[] objects = new MyObject[100];
objects[0] = new MyObject();• 要素の数を指定する必要がある• 格納できる要素の数の上限は後から変更できない• java.utilパッケージにArrayListという便利なクラスがある• 要素の数を最初に決める必要が無い• 便利なメソッドが備わっている

型を指定するクラス
型パラメータを指定したArrayListオブジェ
クトの⽣成
ArrrayList<String> array= new ArrayList<String>();・< >の中に配列に格納するオブジェクトの型を指定する ←型パラメータ
・ここで指定した型のオブジェクトだけを格納できるようになる・上の例ではString型を指定

ジェネリクス• API仕様書でArrayListを⾒るとクラス名が次のようになっている
ArrayList<E>• EはArrayListに格納できるオブジェクトのクラスを指定する型パラメータ• getメソッドは次のように記述されている
public E get(int index)• 戻り値の型がEとなっている。型パラメータで指定したクラスの参照が戻り値。
• 特定のクラスに特化したArrayListにできる。

ラッパークラス• ArrayListに格納できるのは参照型• 基本型の値は格納できない• 「ArrayList<int>」は誤り• ラッパークラスを使⽤する• ラッパークラスとは基本型をオブジェクトとして扱うためのクラス
ArrayList<Integer> arr =new ArrayList<Integer>();arr.add(new Integer(50));
Integer integer0 = arr.get(0);int i = integer0.intValue();基本型とそれに対応するラッパークラス

コレクションフレームワーク• 実際のプログラムでは、複数の（多数の）オブジェクトを扱うことが多い• 配列よりも便利に使えるクラスがJavaには予め多数準備されている。これらをコレクションフレームワークと呼ぶ（ArrayListもこれに含まれる）• ⽬的に応じて使い分ける– 膨⼤な数のオブジェクトから⽬的のオブジェクトを素早く取り出したい– 同じインスタンスへの参照が重複して格納されないようにしたい– キーワードを使ってオブジェクトを取りだしたい– 特定の値で並び変えたい• ⼤きく分けると、リスト・マップ・セットの3種類

リスト• オブジェクトが順番に並ぶ• 「先頭から2番⽬のもの」「最後に追加したもの」を取りだすことができる• 異なる要素が同⼀のオブジェクトを参照できる• Listインタフェースを実装する

マップ• キーと値（オブジェクト）のペアを管理する• キーでオブジェクトを取りだせる• キーは重複してはいけない• Mapインタフェースを実装する

セット• 格納されるオブジェクトに重複がないことを保証する• 個々のオブジェクトを指定して取りだす⽅法が無い（リストやマップと組み合わせて使⽤する）• Setインタフェースを実装する

リストコレクション：ArrayList• 配列＋便利な機能• インデックスで直接要素にアクセスできるので⾼速• 要素の追加と削除には内部で要素のコピーが⾏われるので低速リストコレクション：LinkedList• 要素の追加と削除は⾼速• インデックスを指定しての要素へのアクセスは低速マップコレクション：HashMap
キーと値に使⽤する型を型パラメータで指定する

HashMap<String, String> map =new HashMap<String, String>();map.put("住所", "茨城県つくば市");
map.put("氏名", "Java 太郎");
System.out.println(map.get("住所"));
System.out.println(map.get("氏名"));セットコレクション：HashSet
キーと値に使⽤する型を型パラメータで指定する

HashSet<String> set =new HashSet<String>();map.add("Jan");
map.add("Feb");
System.out.println(set); // 要素を全て出力
System.out.println(set.contains("Jan"));コレクションに含まれる全要素へのアクセス
これまでに学習したfor⽂を使うと、次のようにしてArrayListの全要素にアクセスできる
ArrayList<String> list = new ArrayList<String>();list.add("Good morning.");list.add("Hello.");for(int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}•••

この⽅法は、インデックスを指定して要素にアクセスできるものにしか使えない
インデックスを指定したアクセスが低速なコレクションには適さない
他にも全要素にアクセスする⽅法があるイテレータ（Iterator）• イテレータは、コレクションの中の要素を1つずつ順番に参照する能⼒をもつオブジェクト• 主に次の2つのメソッドがある
boolean hasNext() まだ要素があるかE next() 現在参照している要素を返して、次の要素に移動する

イテレータ（Iterator）の使⽤例
HashSet<String> set = new HashSet<String>();set.add("A");
set.add("B");
set.add("C");
set.add("D");Iterator<String> it = set.iterator();
while(it.hasNext()) {String str = it.next();
System.out.println(str);}
セットコレクションに対しても、1つずつ要素を参照できる。

拡張for⽂
通常のfor⽂、イテレータを使ったアクセスよりも簡潔に記述できる構⽂
for(型名 変数名 : コレクション) {forループ内の処理}

ArrayList<String> list = new ArrayList<String>();list.add("Good morning.");list.add("Hello.");for(String str : list) {System.out.println(str);}LinkedListクラスによるキュー
キュー：先⼊れ先出し（First In First Out:FIFO）
によるオブジェクト管理

Queueインタフェースの使⽤
Queue<String> queue = new LinkedList<String>();queue.offer("(1)");
System.out.println("キューの状態:" + queue);queue.offer("(2)");
System.out.println("キューの状態:" + queue);queue.offer("(3)");
System.out.println("キューの状態:" + queue);queue.offer("(4)");
System.out.println("キューの状態:" + queue);
while(!queue.isEmpty()) {System.out.println("要素の取り出し:" + queue.poll());
System.out.println("キューの状態" + queue);}

LinkedListクラスによるスタック
スタック：後⼊れ先出し（Last In First
Out:LIFO）によるオブジェクト管理LinkedListのスタックとしての利⽤
LinkedList<String> stack = new LinkedList<String>();stack.push("(1)");
System.out.println("スタックの状態:" + stack);
stack.push("(2)");
System.out.println("スタックの状態:" + stack);
stack.push("(3)");
System.out.println("スタックの状態:" + stack);
stack.push("(4)");
System.out.println("スタックの状態:" + stack);
while(!stack.isEmpty()) {System.out.println("要素の取り出し:"+stack.pop());
System.out.println("スタックの状態" + stack);}

sortメソッドによる並べ替え• コレクションに格納された要素を値の⼤⼩で並べ替えたいことがよくある• Collectionsクラスのsortメソッドで、Listインタ
フェースを実装したコレクション（ArrayList,
LinkedListなど）の要素の並び替えを⾏える

ArrayList<String> list = new ArrayList<String>();// listに要素を追加する処理
Collections.sort(list); // 並び替え実行⾃作クラスのインスタンスの並び替え
⾃分で作ったクラスを順番に並び替える場合は、⼤⼩をどのように決定するのか明らかにしておく必要がある。

Comparableインタフェースを実装する

public int comapareTo(クラス名 変数名)
メソッドを実装する

Comarableインタフェースの実装例
class Point implements Comparable<Point> {int x;
int y;
Point(int x, int y) {this.x = x;this.y = y;}public int compareTo(Point p) {return (this.x + this.y) - (p.x + p.y);}}ArrayList<Point> list = new ArrayList<Point>();// listに要素を追加する処理
Collections.sort(list); // 並び替え実行

第6章 ラムダ式

内部クラス
クラスの宣⾔を別のクラスの内部で⾏える
class Outer {class Inner {}}内部クラスは外部クラスのプライベート宣⾔された変数にもアクセスできる匿名クラス• メソッドの引数を指定するカッコの中で、「クラスを定義すること」と「そのインスタンスを⽣成すること」の両⽅を⾏える → クラスの名前が不要• その場だけで必要なクラスの作成に使える匿名クラスの例
interface SayHello {public void hello();}class Greeting {static void greet(SayHello s) {s.hello();}}public class AnonymousClassExample {public static void main(String[] args) {Greeting.greet(new SayHello() {public void hello() {System.out.println("こんにちは");
}
});
}
}

関数型インタフェース
抽象メソッドを1つしか含まないインタフェースのこと
interface SayHello {public void hello();}
関数型インタフェースを引数の型に持つメソッド

class Greeting {static void greet(SayHello s) {s.hello();
}
}

ラムダ式
関数型インタフェースを実装したクラスの宣⾔を短く記述するための構⽂。
Greeting.greet(new SayHello() {public void hello() {System.out.println("こんにちは");}});

Greeting.greet( () -> {System.out.println("こんにちは");} );ラムダ式の記述⽅法(引数列) -> {処理内容}
引数がない例() -> {System.out.println("こんにちは");}引数が1つの例(int n) -> { return n + 1;}
引数が2つの例(int a, int b) -> { return a+b;}ラムダ式の省略形
引数列の型は省略できる
元のラムダ式： (int n) -> { return n + 1; }省略形： (n) -> { return n + 1; }引数が⼀つだけの場合、引数を囲む( )を省略できる
元のラムダ式： (n) -> { return n + 1; }省略形： n -> { return n + 1; }

ラムダ式の省略形
処理の中⾝に命令⽂が1つしかない場合、処理を囲
む{ }とreturnキーワード、セミコロン（;）を省略できる。
元のラムダ式： n -> { return n + 1; }省略形： n -> n + 1;

ラムダ式の省略形を使った例
interface SimpleInterface{public int doSomething(int n);}
public class LambdaExample {static void printout(SimpleInterface i) {System.out.println(i.doSomething(2));}
public static void main(String[] args) {printout(n -> n + 1);}}

forEachメソッドとラムダ式• ArrayListの要素にアクセスするために拡張for⽂を⽤いる以外にもforEachメソッドを使⽤できる• ラムダ式と組み合わせることで各要素に対する処理を簡潔に記述できるfor(Point p : pointList) {p.x *= 2;
p.y *= 2;}
for(Point p : pointList) {p.printInfo()}

pointList.forEach( p -> {p.x *= 2; p.y *= 2;} );pointList.forEach( p -> p.printInfo() );ラムダ式を⽤いた並べ替え• 各コレクションクラスに備わっているsortメソッ
ドを使⽤すると、Comparableインタフェースを実装していないオブジェクトも並べ替えできる• sortメソッドの引数に「どのように順序付けするか」を記述したラムダ式を渡す(Point p0, Point p1) -> {2つのPointオブジェクトに対して順序付けを行うための処理}ラムダ式を⽤いた並べ替えの例
Pointクラスのインスタンス変数xとyの値を⾜し合わせた値で順序付けし、昇順に並べる
pointList.sort((p0, p1) -> (p0.x + p0.y) - (p1.x + p1.y));第7章 ⼊出⼒

⼊出⼒
⼊⼒：プログラムにデータが⼊ってくること– ファイルからのデータの読み込み– キーボードで⼊⼒されたデータの読み込み– ネットワーク通信によるデータの読み込み

出⼒：プログラムからデータを送りだすこと– 画⾯への表⽰– ファイルへの保存– ネットワーク通信による送信– プリントアウト• ストリームオブジェクトがデータの橋渡しをする• 扱うデータは「⽂字列データ（Unicode,16ビット単位）」と「バイナリデータ（8ビット単位）」に分け
られる

標準出⼒
⼊出⼒先を特に指定しなかった場合に標準的に使⽤される出⼒。⼀般的には「コンソール」。

標準出⼒への⽂字列の出⼒
System.out.println("こんにちは");標準⼊⼒
標準⼊⼒からの⽂字列の受け取り

InputStreamReader in =new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(in);try {String str = reader.readLine();} catch(IOException e) {}⽂字列と数値の変換• 標準⼊⼒から渡されるデータは⽂字列• 「10」という⽂字列を数値として処理できるよ
うにするには、次のような変換が必要
String str0 = "10";int i = Integer.parseInt(str0);
String str1 = "0.5";
double d = Double.parseDouble(str1);

ファイルへの出⼒

try {File file = new File("C:¥¥java¥¥test.txt");
FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw);for(int i = 0; i < 5; i++) {bw.write("[" + i + "]¥r¥n");}bw.close();} catch (IOException e) {System.out.println(e);}バッファを⽤いたデータの書き込み

バッファを⽤いたデータの読み込み

ストリームの連結• ストリームは最低1つ必要• ⽬的に応じてストリームを複数連結できる

ファイルからの⼊⼒

try {File file = new File("C:¥¥java¥¥test.txt");
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);String s;
while((s = br.readLine()) != null) {System.out.println(s + "を読み込みました");}
br.close();} catch (IOException e) {System.out.println(e);}シリアライゼーションとオブジェクトの保存プログラムの状態をファイルに保存する（⼀度プログラムを終了させて、後から続きを⾏うときなどに必要）

⽅法1.テキストファイルに⽂字列で情報を書き込む
⽅法2.シリアライゼーションによってオブジェクト
そのものをファイルに保存するシリアライゼーション• オブジェクトをその状態を保持したままファイルに書き出すことができる• このことをシリアライゼーションと⾔う• ファイルに書き出せるオブジェクトは、Serializableインタフェースを実装している必要がある。実装すべきメソッドは何もないので、宣⾔するだけclass Point implements Serializable {int x;
int y;}

シリアライゼーションを使⽤したオブジェクトの保存

try {FileOutputStream fs =new FileOutputStream("C:¥¥java¥¥triangle.ser");
ObjectOutputStream os = new ObjectOutputStream(fs);os.writeObject(/* 出力するオブジェクトへの参照 */);
os.close();} catch(IOException e) {System.out.println(e);}保存したオブジェクトの再現

try {FileInputStream fs = new
FileInputStream("C:¥¥java¥¥triangle.ser");
ObjectInputStream os = new ObjectInputStream(fs);
MyObject obj = (MyObject)os.readObject();
os.close();} catch(IOException e) {System.out.println(e);} catch (ClassNotFoundException e) {System.out.println(e);}ファイルとフォルダの操作• java.io.Fileクラスを使って、ファイルとフォルダの操作を⾏える。
• Fileオブジェクトの作成
File file = new File("C:¥¥java¥¥test.txt");
Fileクラスのファイル操作のための主なメソッド

boolean exists()

ファイルが存在するかどうか確認する

boolean delete()boolean renameTo(File dest)

ファイルを削除する
名前を変更するフォルダ操作• フォルダもファイルと同じように
java.io.Fileクラスを使⽤する• Fileオブジェクトの作成
File file = new File("C:¥¥java");
Fileクラスのフォルダ操作のための主なメソッド

String[] list()boolean mkdir()boolean mkdirs()
boolean delete()

フォルダに含まれるファイルの⼀
覧を返す
フォルダを作成する階層を持ったフォルダを⼀度に作成する
フォルダを削除する

第8章 GUIアプリケーション

GUIアプリケーションとは• GUI: Graphical User Interface• CUI: Character-based User Interface

Swingライブラリ• ウィンドウ、ボタン、メニューなどを扱うクラス群を集めたライブラリ• javax.swingパッケージに含まれる• GUIアプリケーションを扱うには、ユーザの操作に応答するためのイベント処理が必要

フレームの作成
import javax.swing.*;class SimpleFrameExample {public static void main(String[] args) {JFrame frame = new JFrame();frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
frame.setVisible(true);}}⾃分⾃⾝のインスタンスを⽣成するクラス
import javax.swing.*;
public class MyFrame extends JFrame {public static void main(String[] args) {new MyFrame();}MyFrame() {setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 200);
setVisible(true);}}コンポーネントの配置• ボタンやチェックボックスなどのGUI部品は「コンポーネント」と呼ばれる• コンポーネントは、コンテナの上に配置される。

JButton（ボタン）コンポーネントの配置
import javax.swing.*;
public class MyFrame extends JFrame {public static void main(String[] args) {new MyFrame();}MyFrame() {setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().add(new JButton("ボタン"));
setSize(300, 200);
setVisible(true);}}
ボタンを配置しただけなので、クリックしても何も起こらないボーダーレイアウト• JFrameクラスのgetContentPaneメソッドで取得できるコンテナはBorderLayoutと呼ばれる⽅法でコン
ポーネントが配置される• 配置場所を5つから選択して指定できるadd(BorderLayout.WEST, new JButton("ボタン"));ボーダーレイアウトの配置例
getContentPane().add(BorderLayout.CENTER, new JButton("CENTER"));
getContentPane().add(BorderLayout.SOUTH, new JButton("SOUTH"));
getContentPane().add(BorderLayout.WEST, new JButton("WEST"));
getContentPane().add(BorderLayout.EAST, new JButton("EAST"));
getContentPane().add(BorderLayout.NORTH, new JButton("NORTH"));
setSize(300, 200);
setVisible(true);

ウィンドウサイズを変えると、ボタンのサイズが⾃動調整される

ボーダーレイアウトの配置例
コンポーネントの数に応じて、⾃動的に⼤きさが調整される

WESTに配置しなかった場合

CENTER,SOUTHのみ
配置した場合レイアウトマネージャ• レイアウトマネージャがコンポーネントをどこに、どの⼤きさで配置するかを決定する。
• 各種のレイアウトマネージャが準備されている。それぞれ、レイアウト⽅法が異なる。
– BorderLayout– FlowLayout– BoxLayout– GridLayout• レイアウトマネージャを変更するには、コンテナのsetLayoutメソッドを使⽤する

フローレイアウト
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new FlowLayout());
getContentPane().add(new JButton("1 January"));getContentPane().add(new JButton("2 February"));getContentPane().add(new JButton("3 March"));getContentPane().add(new JButton("4 April"));getContentPane().add(new JButton("5 May"));getContentPane().add(new JButton("6 June"));setSize(300, 200);
setVisible(true);ボックスレイアウト
getContentPane().setLayout(
new BoxLayout(getContentPane(), BoxLayout.Y_AXIS);

グリッドレイアウト
getContentPane().setLayout(
new GridLayout(2, 3));

パネルを活⽤したレイアウト• JPanelはコンポーネントをのせることができるコンポーネント• JPanelを活⽤することで、複雑なコン
ポーネントの配置が可能になるイベント処理• 「ボタンがクリックされた」などのように、ユーザによって何か操作が⾏われたことを「イベントが発⽣した」という• Javaでは、イベントオブジェクト(java.awt.Event)によって、イベントが表現される• イベントが発⽣したときの処理をイベント処理という

ソースとリスナ• ソース（source）– イベントを発⽣するオブジェクトのこと– JButtonなどのコンポーネントに限られる• リスナ（listener）– イベントを受け取るオブジェクトのこと– 必要なインタフェース（リスナインタフェース）を実装しているクラスがリスナになれるイベント処理（ボタン押下時の処理）を⾏うプログラムの作成

1. リスナを作成する– イベント通知を受け取るクラスを作成する– ActionListenerインタフェースを実装する– イベントが発⽣すると、actionPerformedメ
ソッドが呼び出される

2. ソースにリスナを登録する– イベントが発⽣した時に、その通知を誰に送るのかをソースに登録する←リスナ登録。
– リスナ登録はaddActionListenerメソッドで⾏うイベント処理の様⼦• リスナ登録したオブジェクト（SimpleButtonExampleオブジェクト）へイベ
ントが通知される（actionPerformedメソッドが呼び出される）複数のコンポーネントがある場合• 異なるボタンに対して、同じオブジェクトをリスナ登録している場合は、同じように
actionPerformedメソッドが呼ばれる• 引数で渡されるActionEventオブジェクトの
getSourceメソッドでイベント通知元のオブジェクトを判別できるさまざまなコンポーネント• Swingライブラリには、さまざまなコン
ポーネントがある• 必要に応じてAPI仕様書を調べてみよう第9章
グラフィックスとマウスイベント

JPanelを使ったグラフィックス描画
・描画を⾏うためのパネルクラスの作成（JPanelを継承）
・paintComponentメソッドをオーバーライドする
・引数のGraphicsオブジェクトを使って描画
import java.awt.*;
import javax.swing.*;
public class MyPanel extends JPanel {public void paintComponent(Graphics g) {g.fillRect(50, 30, 150, 100);}}

・作成したパネルクラスを配置する
getContentPane().add(new MyPanel());

Graphiscオブジェクトの座標系
描画領域の⼤きさはコンポーネントのgetSizeメソッドで取得できる

直線の描画
public void paintComponent(Graphics g) {Dimension d = getSize();g.drawLine(0, 0, d.width, d.height);
g.drawLine(0, d.height, d.width, 0);}様々な描画メソッド• drawArc• drawLine• drawOval• drawPolygon• drawPolyline• drawRect• drawString• setColor

円弧を描く
直線を描く
楕円を描く
多⾓形を描く折れ線を描く⻑⽅形を描く
⽂字列を描く
描画⾊を指定する

Graphics2Dクラス• Graphicsクラスよりも⾼機能なグラ
フィックス機能を提供する（グラデーション、アンチエイリアシング、線の太さ、線のスタイルの指定など）• paintComponentメソッドの引数のGraphicsオブジェクトをキャストして使⽤できる
public void paintComponent(Graphics g) {Graphics2D g2d = (Graphics2D)g;// Graphics2Dのメソッドを使った描画}

マウスイベント• マウスクリック、カーソルの移動、ドラッグ操作などもイベントの1つ• イベント処理によって、マウスで操作できるプログラムを作成できる• 以下ものが必要
1. リスナ登録
2. リスナインタフェースの実装
3. イベントが通知された時の処理

2つのイベントリスナ• MouseListenerインタフェース
void mouseClicked(MouseEvent e)void mouseEntered(MouseEvent e)void mouseExited(MouseEvent e)void mousePressed(MouseEvent e)void mouseReleased(MouseEvent e)• MouseMotionListenerインタフェース
void mouseDragged(MouseEvent e)void mouseMoved(MouseEvent e)• それぞれ次のメソッドでリスナ登録する
addMouseListener
addMouseMotionListenerimport java.awt.event.*;
import javax.swing.*;class MyPanel extends JPanel
implements MouseListener, MouseMotionListener {public MyPanel() {addMouseListener(this);
addMouseMotionListener(this);}public void mouseClicked(MouseEvent e) {}public void mouseEntered(MouseEvent e) {}public void mouseExited(MouseEvent e) {}public void mousePressed(MouseEvent e) {}public void mouseReleased(MouseEvent e) {}public void mouseDragged(MouseEvent e) {}public void mouseMoved(MouseEvent e) {}}第10章 ネットワーク

ネットワーク接続• ⼀般的にTCP/IPというプロトコルが⽤いられることが多い• ⼀⽅をサーバー、他⽅をクライアントと呼ぶ

IPアドレスとポート番号• クライアントがサーバーに接続要求を出す• サーバーのIPアドレスと、サーバー側のプ
ログラムが使⽤するポート番号を知っている必要があるIPアドレスの例：192.168.1.11
ポート番号の例：5000番

ServerSocketとSocket

サーバー側のプログラム例
try {ServerSocket serverSocket = new ServerSocket(5000);
while(true) {Socket socket = serverSocket.accept();
PrintWriter writer =new PrintWriter(socket.getOutputStream());
writer.println("こんにちは。私はサーバです。");
writer.close();}} catch(IOException e) {System.out.println(e);}クライアント側のプログラム例
try {Socket socket = new Socket("127.0.0.1", 5000);
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String message = reader.readLine();System.out.println("サーバーからの文字列:" + message);reader.close();} catch(IOException e) {System.out.println(e);}第11章 ⼀歩進んだ
Javaプログラミングコレクションとストリーム• コレクションに格納されたオブジェクトを扱うために拡張for⽂やforEachメソッドを使って⼀つ⼀つ取り出す⽅法がある• ストリームという概念を使えば、たくさんのプログラムコードが必要だった処理を短く直感的に記述できる

ストリームオブジェクトのまとまりに対して、なにかしらの処理を⾏って、最後に出⼒を⾏うストリームの⽣成
List<String>型のコレクションに対するstreamメソッドを利⽤
List<String> list = Arrays.asList("January","February","March");Stream<String> stream = list.stream();Streamインタフェースのofメソッドを利⽤
Stream<String> steam = Stream.of("January","February","March");ストリームに対する終端操作
ストリームに対する⼀連の操作の最後に⾏う作成したストリームからオブジェクトを1つずつ取り出してコンソールに出⼒
List<String> list = Arrays.asList("January","February","March");list.stream().forEach(s -> System.out.println(a));

listに含まれる要素数をコンソールに出⼒Long n = list.stream().count();
System.out.println(n);ストリームに対する中間操作• filterメソッドは、ある条件を満たすオブジェク
トだけを取り出して次の操作に渡すことができる
条件に合うオブジェクトの数を取得
long l = list.stream().
filter(s -> s.length() > 5).
count();※戻り値がStreamオ
ブジェクトなので別のメソッドをドット（.）
で連結できる。

• mapメソッドは、個々のデータを別のオブジェク
トにマッピングできる前後を[]で囲った⽂字列を出⼒
list.stream().
map(s -> "[" + s + "]").
forEach(s -> System.out.println(s));

ストリームに対する中間操作• Sortedメソッドはデータを並べ替えることができる。
⽂字列の⻑さで並べ替える
sorted((s0, s1) -> s0.length() - s1.length())

ストリーム処理の例
List<String> list = Arrays.asList("January","February", "March", "April", "May","June","July", "August", "September","October", "November","December");listに格納された⽂字列の⽂字数が5以下のものに対して、アルファベット
順で並べ替え、⽂字列の両端に"["と"]" 記号をつけて、最後に1つ1つ出⼒
list.stream().
filter(s -> s.length() <= 5).
sorted().
map(s -> "[" + s + "]").
forEach(s-> System.out.println(s));

スタティックインポート
パッケージ名とクラス名を省略して、クラス変数
やクラスメソッドを直接記述できる

import static java.lang.Math.PI;
import static java.lang.Math.abs;
public class StaticImportExample {public static void main(String[] args) {System.out.println("PI=" + PI);
System.out.println("abs(-2)=" + abs(-2));}}

インタフェースのデフォルトメソッド• インタフェースのメソッドにdefault(デフォルト)
修飾⼦をつけるとメソッドの中⾝を記述できる• デフォルトメソッドを宣⾔すれば、メソッドをオーバライドせずに済ませられる• 通常のインタフェースと同様にオーバーライドすることもできる
interface SayHello {default void hello() {System.out.println("Hello");}}デフォルトメソッドの例
interface SayHello {default void hello() {System.out.println("Hello");}}class EnglishGreet implements SayHello {}class JapaneseGreet implements SayHello {public void hello() {System.out.println("こんにちは");}}
SayHello a = new EnglishGreet();
SayHello b = new JapaneseGreet();a.hello(); →Helloと出力
b.hello(); →こんにちはと出力アノテーション• メソッド名の前の@Overrideなど、記号(@)を先頭に持つ表記• 「このメソッドはスーパークラスまたはインタ
フェースのメソッドをオーバーライドしたものである」ということをコンパイラに伝える役割を持つ• 適切にオーバーライドができていないときに、
コンパイラがエラーを出す

System.out.printfメソッド
⽂字列の中の特別な記号（%d, %fなど）を、引数で指定した変数の値に置き換えることができる
int x = 5;
int y = 10;
int z = 15;
System.out.printf("x=%d%n", x);
System.out.printf("(x,y)=(%d,%d)%n", x,y);System.out.printf("(x,y,z)=(%d,%d,%d)%n",x,y,z);%d 整数、 %f ⼩数を含む値、 %s ⽂字列、%n 改⾏

enum宣⾔
特定の定数の値だけを取れる独⾃の型を定義できる

class Student {enum Gender { MALE, FEMALE };String name;
Gender gender;}
Student s = new Student();s.name = "山田太郎";
s.gender = Student.Gender.MALE;

== 演算⼦とequalsメソッド• ==演算⼦を使って2つのオブジェクト参照を⽐較した場合、両⽅が同⼀のインスタンスを参照
している場合はtrue,そうでない場合はfalse• equalsメソッドはObjectクラスに備わっているメソッド。オーバーライドして⾃分で定義できる• コレクションクラスでは、オブジェクトの⽐較にequalsメソッドが使⽤される