Java プログラミング入門
2016/5/21 きしだ なおき
JJUG CCC 2016 Spring
自己紹介
● きしだです。
● 聖闘士星矢をみはじめた
– そろそろ白銀聖闘士が出てくる
今日の話
● × Java(の)プログラミング入門
● ○ Java(で)プログラミング入門
Javaでプログラミング入門
● Javaを使ってプログラミングの入門
● なるべくJava以外でも使える話をします
おわび
● 「Javaプログラミングというからには、Java
でのプログラムの組み方そのものの勉強もやっ
ておいたほうがいいのではないかと思いま
す。」
おわび
● 「このセッションでは、改めてJavaの文法に立
ち戻って、Javaの値や条件分岐、メソッド、型
などを見直し、どのようにプログラムを組み上
げていくかプログラムとは何かということを考
えていきたいと思います。」
Javaでプログラミング入門
● Javaで、プログラムとは何かの入門
プログラムとは
● 値の関係 + 状態遷移 + 入出力
値の関係
● 値の構造
● 操作
– 計算式とか
● 型
状態遷移
● 処理するデータと現在の状態から、次の状態を
決める
● プログラムの状態
– 変数の保持する値
入出力
● 画面に出力
● キーボードから入力
● ネットワークへ出力(送信)
● ネットワークから入力(受信)
● ディスクへ出力(保存)
● ディスクから入力(読込み)
今日の話
● 値の構造
● 操作
– 計算式とか
● 型
プログラムでの値
● 単純な値を組み合わせて複雑な値を表現
● 構造がある
一番単純な値
● 電気のon/offの組み合わせで表せる値
● ブール代数
– true/false
– 1/0 →2進数
コンピュータで表せる関係
● 電気のon/offの組み合わせで表せる関係
● 論理演算
論理演算
● and
● or
● xor
● not
and
● かつ
● 論理積
● 両方trueのときtrue
● & A B A and B
1 1 1
1 0 0
0 1 0
0 0 0
or
● または
● 論理和
● どっちかtrueのときtrue
● | A B A or B
1 1 1
1 0 1
0 1 1
0 0 0
xor
● 排他的論理和
● どっちかだけtrueのときtrue
● ^ A B A xor B
1 1 0
1 0 1
0 1 1
0 0 0
日常生活での「または」
● 「オニギリまたはサンドイッチを
取ってください」
● 「オニギリorサンドイッチを
取ってください?」
● 両方取ってもOK?
日常生活での「または」
● 「オニギリまたはサンドイッチを
取ってください」
● 両方取るとNG
● 「オニギリxorサンドイッチを
取ってください」
not
● 否定
A not A
1 0
0 1
2進数
● 0:false 1:trueとして扱う
● 左からn桁目は2^(n-1)
● 8ビットなら128-64-32-16-8-4-2-1
● 233=0b11101001
● 128+64+32+8+1=233
2進数の演算
● ビット演算
● シフト
ビット演算の使い方
● リセット:全部0にする
● OFF:一部を0にする
● ON:一部を1にする
● TOGGLE:一部を反転する
リセット:全部0にする
● xor
– AとBが同じとき0になる
● 元の値でxorをとると0になる
● 昔のCPUでレジスタを0にするとき使われた
A B A xor B
1 1 0
0 1 1
1 0 1
0 0 0
OFF:一部を0にする
● and
– Bが1のときAの値はそのまま残る
– Bが0のときAの値にかかわらず0になる
● OFFにしたいところを0にした値でandをとる
A B A and B
1 1 1
0 1 0
1 0 0
0 0 0
ON:一部を1にする
● or
– Bが0のときAの値はそのまま残る
– Bが1のときAの値にかかわらず1になる
● ONにしたいところを1にした値でorをとる
A B A or B
1 1 1
0 1 1
1 0 1
0 0 0
TOGGLE:一部を反転する
● xor
– Bが0のときAの値はそのまま残る
– Bが1のときAの値は反転する
● 反転したいところを1にした値でxorをとる
A B A xor B
1 1 0
0 1 1
1 0 1
0 0 0
2進数のシフト
● シフト
– ずらす
● 左にシフト
● 右にシフト
n進数について
● n倍すると左にずれる
– 左にずらすとn倍になる
– 10進数で123を10倍すると1230になる
● 1/n倍すると右にずれる
– 右にずらすと1/n倍になる
– 10進数で123を1/10倍すると12.3になる
2進数のシフト
● 左にシフトすると2倍になる
● 右にシフトすると1/2になる
整数をあらわす
● 何ビット使うか
– int: 32ビット
– long: 64ビット
● 負の数を表せるかどうか
– 表さない→符号なし整数→Javaにはない
– 表す→符号付整数
負の数を表す
● 2の補数
● もうひとけた多いと仮定して引き算する
● 3桁の10進数の場合
– 32 – 53 = -21
● 1032 - 53 = 979
整数の関係
● 足し算
● 引き算
● 掛け算
● 割り算
足し算を論理演算で行う
A B A + B
1 1 10
1 0 1
0 1 1
0 0 0
● 1ビットの足し算
足し算を論理演算で行う
A B 1桁目
1 1 0
1 0 1
0 1 1
0 0 0
● 1桁目を見てみる
● xorだ!
足し算を論理演算で行う
A B 繰上り
1 1 1
1 0 0
0 1 0
0 0 0
● 繰上りをみてみる
● andだ!
● 1ビット左にシフトする
足し算を論理演算で行う
● xorとandとシフトでできる
足し算ができれば
あとの計算もできる
● 引き算
– マイナスの数を足す
● 掛け算
– 掛ける数だけループして足し算
– 筆算
● 割り算
– 割る数が何回引けるか数える
– 筆算
実数はどう扱うか
● どこかを小数点とする→固定小数
– 例:1000倍して整数であらわす
● 3.14159->314159
● 指数を別にあらわす→浮動小数
– Javaはこれ
文字
● 文字に数字をふる
– 'a' -> 97
– '0' -> 34
文字セットと文字コード
● 文字セット
– 文字を集めて番号をふる
– JIS
– UNICODE
● 文字コード
– 文字セットの番号をコンピュータで表現できる形式にする
– Shift_JIS
– UTF-8/UTF-16
いろんな値を扱える
● 数は扱える
● 文字も扱える
● もっといろんな値を扱いたい
● もっといろんな型の値を扱いたい
もっといろんな値を扱いたい
● もっといろんな型の値を扱いたい
値の型
● Javaは型を扱う
● いろいろな種類の型がある
Javaの型の種類
● 型システム入門(TAPL)をベースにした分類
– 基本型
– リスト
– レコード
– 関数型
– Union
– Null
– 総称型
基本型
● 構造を持たない単純な値の集合
● Javaの基本型
– 8つ言えますね?
リスト
● 同じ型の値を複数扱う
● 配列
– int[] a・・・intの値を複数扱う
レコード
● 異なる型の値を名前をつけて複数扱う
● (String x int)、
● Javaの場合は名前をつける必要がある
● クラス・インタフェース
● class A{int p; String q;}と
class B{int p; String q;}は別物
関数型
● 関数の引数と戻り値の型を定義
● Javaでは型として扱えない
– FunctionalInterfaceを使う
● 値としては扱える
– メソッド参照
● Integer::parseInt
– ラムダ式
● n -> Integer.parseInt(n)
Union(積和型)
● 複数の型をとる
● String|Date
– 文字列か日付
● Javaでは一般には使えない
UnionはJavaでは一般には使えない
● 「一般に」
– すべての場合に
● 「一般には使えない」
– すべての場合には使えない
– 一部では使える?
JavaでのUnion
● try {
hoge();
}catch (NumberFormatException|NullPointerException ex) {
log(“困るよ~”);
}
● マルチキャッチはUnion型
null
● 型としてはあらわせない(暗黙の型)
● すべての型のサブタイプとして扱える
● すべて可能
– String s = null;
Integer i = null;
LocalDateTime = null;
多相性
● 「プログラムの一部分を、異なる文脈では異な
る型として用いることを可能にする各種の言語
機構」
● 「一つのコードを複数の型で扱えるようにした
型システム」
多相性の分類
● パラメータ多相
● アドホック多相
● 部分型多相
パラメータ多相
● 型にパラメータを指定できる
● List<T>
– T = String
– List<String>
部分型多相
● サブセットを扱う
● 属性はふえる
– {String, int, boolean}は{String, int}
Javaの部分型
● 名前が必要
● 部分型関係を決めておく必要がある
– class A extends B
● 構造が同じでも、定義時に指定された
部分型関係がなければ、同一に扱えない
– Scalaでは構造的部分型として、構造に同じ部分が
あれば部分型として扱える仕組みがある。
アドホック多相
● 「多相的な値が異なる型として「見られる」と
き、異なったように振る舞うことを可能に
する」(TAPL)
● オーバーロード(静的型解決)
● 動的型解決
オーバーロード
● 実際に呼び出されるメソッドが変わる
● コンパイル時に解決される
– 静的ディスパッチ
void hoge(Object o) {
}
void hoge(String s) {
}
void main() {
String s = “こんにちは”;
Object o = s;
hoge (o);
}
Javaでの動的型解決
● 例外のcatch
●
try {
Exception ex = new NullPointerException();
throw ex;
} catch (NullPointerException ex) {
} catch (Exception ex) {
}
型がなんで大事か
こういうときどうしますか?
● Hoge型の値をもっている
● こんなメソッドがある
– Foo getFoo(Hoge h);
– Bar createBar(Foo f);
● こんなメソッドを作りたい
– Bar toBar(Hoge h);
こう
● Bar toBar(Hoge h) {
Foo f = getFoo(h);
Bar b = createBar(f);
return b;
}
簡単に表現
● Function<Hoge, Bar> some(
Function<Hoge, Foo> f1,
Function<Foo, Bar> f2)
は実装できるか?
こうなる
●
Function<Hoge, Bar> some(
Function<Hoge, Foo> f1,
Function<Foo, Bar> f2) {
return Hoge h -> f2.apply(f1.apply(h));
}
これは実装できる?
● Function<Hoge, Bar> some(
Function<Hoge, Foo> f1,
Function<Bar, Foo> f2)
は実装できるか?
こうなる
● Function<Hoge, Bar> some(
Function<Hoge, Foo> f1,
Function<Bar, Foo> f2)
は他の関数が与えられないと実装できない
ところで、これ正しいですか?
● 前提
– サバならば魚
– 魚ならば泳ぐ
● 結論
– サバならば泳ぐ
じゃあ、これは?
● 前提
– イルカならば泳ぐ
– 魚ならば泳ぐ
● 結論
– イルカならば魚
証明方法
● 命題
– 前提
● サバならば魚
● 魚ならば泳ぐ
– 結論
● サバならば泳ぐ
● 「ならば(⇒)」という論理演算の導入
● 命題を記号化する
● 命題を式であらわす
「ならば(⇒)」という
論理演算の導入
● ならば(⇒)
● Aがtrueのとき、Bがfalseだったらだめ
● Aがfalseのときはtrue?
A B A B⇒
1 1 1
1 0 0
0 1 1
0 0 1
「ならば(⇒)」
●
命題:「きしだ」ならば「前日までに資料できてない」
●
「きしだ」であり「前日までに資料できてない」とき
– true
●
「きしだ」であり「前日までに資料できている」とき
– false→なにかおかしい
●
「きしだ」じゃないとき
「前日までに資料できてない」でも
「前日までに資料できてる」でも
true
A B A B⇒
1 1 1
1 0 0
0 1 1
0 0 1
命題を記号化する
● 命題
– 前提
● サバならば魚
● 魚ならば泳ぐ
– 結論
● サバならば泳ぐ
● サバ -> A, 魚-> B, 泳ぐ -> C
こうなる
● 前提
– AならばB
– BならばC
● 結論
– AならばC
命題を式であらわす
● 命題
– 前提
● AならばB
● BならばC
– 結論
● AならばC
● 前提はandで結ぶ
● 前提と結論は「ならば⇒」で結ぶ
こうなる
● ((A⇒B)and(B⇒C))⇒(A⇒C)
証明
● 前提=P, 結論=Rで表す
● A, B, Cの各値の組み合わせについて
P⇒Rはどうなるか
証明
● ((A⇒B)and(B⇒C))⇒(A⇒C)
● P⇒Rがすべて真
● 恒真式。常になりたつ
A B C A B⇒ B C⇒ (A B)and(B C)⇒ ⇒ :P A C⇒ :R P R⇒
1 1 1 1 1 1 1 1
1 1 0 1 0 0 0 1
1 0 1 0 1 0 1 1
1 0 0 0 1 0 0 1
0 1 1 1 1 1 1 1
0 1 0 1 0 0 1 1
0 0 1 1 1 1 1 1
0 0 0 1 1 1 1 1
A B A B⇒
1 1 1
1 0 0
0 1 1
0 0 1
証明
● ((A⇒B)and(C⇒B))⇒(A⇒C)
● P⇒Rがすべて真ではない
● 恒真式ではない。なりたたないことがある
A B C A B⇒ C B⇒ (A B)and(C B)⇒ ⇒ :P A C⇒ :R P R⇒
1 1 1 1 1 1 1 1
1 1 0 1 1 1 0 0
1 0 1 0 0 0 1 1
1 0 0 0 1 0 0 1
0 1 1 1 1 1 1 1
0 1 0 1 1 1 1 1
0 0 1 1 0 0 1 1
0 0 0 1 1 1 1 1
A B A B⇒
1 1 1
1 0 0
0 1 1
0 0 1
似てないですか?
● 実装できる
– Function<Hoge, Bar> some(
Function<Hoge, Foo> f1, Function<Foo, Bar> f2)
● 正しい
– 前提
● サバならば魚
● 魚ならば泳ぐ
– 結論
● サバならば泳ぐ
Functionを「ならば」とおく
● 論理の命題
– 前提
● サバならば魚
● 魚ならば泳ぐ
– 結論
● サバならば泳ぐ
● 関数
– ならば<サバ, 泳ぐ> some(
ならば<サバ, 魚> f1, ならば<魚, 泳ぐ> f2)
完全に一致
● ならば<サバ, 泳ぐ> some(ならば<サバ, 魚> f1, ならば<魚, 泳
ぐ> f2)
● 変換
– ならば→Function
– サバ→Hoge
– 魚→Foo
– 泳ぐ→Bar
● Function<Hoge, Bar> some(
Function<Hoge, Foo> f1, Function<Foo, Bar> f2)
正しくない推論は
● 命題
– 前提
● イルカならば泳ぐ
● 魚ならば泳ぐ
– 結論
● イルカならば魚
● 関数
– ならば<イルカ, 泳ぐ> some(
ならば<イルカ, 泳ぐ> f1, ならば<魚, 泳ぐ> f2)
実装できない
● ならば<イルカ, 泳ぐ> some(ならば<イルカ, 泳ぐ> f1, ならば<
魚, 泳ぐ> f2)
● 変換
– ならば→Function
– イルカ→Hoge
– 魚→Foo
– 泳ぐ→Bar
● Function<Hoge, Bar> some(
Function<Hoge, Bar> f1, Function<Foo, Bar> f2)
どういうことなの
● 関数と型を論理の命題に対応づけることが
できる
だからどういうことなの
● 関数と型によってコンパイルが通るプログラム
を書くことは、対応する論理の命題を
証明することになる
ようするになんなの
● 型をつかってプログラムを書いていると
思ったら論理の証明をしていた
カリー=ハワード同型対応
● カリーさんとハワードさんがみつけた
● プログラムと論理命題が対応するという不思議な関係
● ならば(⇒)
– 関数
● and
– 複数の引数
● or
– Union
orをJavaでどうやろう?
● JavaにはUnionがない
● 「卵が安い」または「冷蔵庫に卵がない」
ならば「卵を買う」
● 卵を買う some(
卵が安い | 冷蔵庫に卵がない a)
オーバーロード(アドホック多相)
● 「卵が安い」または「冷蔵庫に卵がない」
ならば「卵を買う」
● オーバーロードで表現
– 卵を買う some(卵が安い a)
– 卵を買う some(冷蔵庫に卵がない a)
● 戻り値にORを使えない
– 傘 | 休む some(雨が降る a)
継承を使う(部分型多相)
● 「卵が安い」または「冷蔵庫に卵がない」
ならば「卵を買う」
● 型を定義
– interface 卵条件{}
– interface 卵が安い extends 卵条件{}
– interface 冷蔵庫に卵がない extends 卵条件{}
– 卵を買う some(卵条件 a)
● 戻り値にも使える
型の重要性
● 型が高機能だとさまざまな論理が
証明しやすくなる
● 正しく動くプログラムが書きやすくなる
今日のまとめ
● 値を組み合わせれればいろんな値が扱える
● いろんな値は型として表す
● 型を組み合わせるといろんな型が実現できる
● Javaにも案外いろんな型がある
● 型を考えることで、正しく動くプログラムを
考えることになる
Javaプログラミング再入門
● プログラムを考えることに入門
できたでしょうか
● 門の入り口まで来れたでしょうか
● 門があること、がイメージできればうれしい

Javaプログラミング入門