Java SE8 Gold (1)
Java SE8 Gold 研修(1日目)に行ったのでメモ.
だいたい参考書とかに出ている話題.参考にならないかも.
抽象クラス及び内部クラス
抽象クラス
一部のメソッドが完成していないテンプレート的なクラス
抽象メソッドは未完成で実装がない
スーパークラスの抽象メソッドをサブクラスでオーバーライドして実装を完成させる
つまり継承が前提でサブクラスで実装する必要がある(差分プログラミングを実現している)
文法上の留意点
- クラス名の前に
abstract
をつける - 抽象クラス自身は
new
できない - 抽象メソッドも定義できる.アクセス修飾子は
private
以外指定できる - 抽象メソッドを継承した通常クラスは,抽象クラスが持つ抽象メソッドを全て実装する必要がある
- 抽象メソッドを継承した抽象クラスは,継承元の抽象クラスが持つ抽象メソッドを全て実装する必要がない
何故抽象クラスがあるのか
- クラスの継承により,クラス毎のコード複製を防ぎつつ,
特化により子クラス側でオーバーライドを行い独自の実装ができる - 通常クラスだけでは子クラスで行うべき親クラスのメソッドの実装を強制できない
→ 抽象クラスを活用
final
finalメソッド
final
メソッドはオーバーライドできない
finalクラス
final
クラスは拡張できない
final変数
- 初期化後,変更できない
- 初期化されていない場合,コンストラクタでのみ初期化設定が可能
- final参照は常にオブジェクトを参照するが,オブジェクト内容は変更可能
<利点と欠点>
- バグの防止
- スレッド・セーフ
final変数の不変性(immutable)により,複数スレッドによる同時スレッドに伴い問題がなくなる - オブジェクトへのfinal参照
finalオブジェクト参照は,他のオブジェクトへの参照を防止するだけ.
final参照にはnull
を割り当てられない.
オブジェクト参照を保持することで,そのオブジェクトがGC対象になることを防ぐことができる
内部クラス
メンバークラス
外部クラスがインスタンス化されて初めてインスタンス化できる.
このクラスはこの外部クラスにだけ使いたい場合の時に使ったりする.
静的内部クラス(Static Inner Class)
外部クラスのインスタンス化されなくてもインスタンスが使える.
このクラスはこの外部クラスにだけ使いたい場合の時に使ったりする.
匿名クラス(無名内部クラス)
インターフェースやクラスのインスタンスが必要な場合,
名前を付けずにクラス定義を行いつつnew
してインスタンスを生成する.
GUI系で使うことが多い.
列挙型
曜日や和暦,男女等に使う.
Javaクラスのバリエーションを使用して作成される.
コンパイル時の範囲チェックを指定できる.
型安全である.列挙型を利用しなかった場合,
例えば整数型で曜日の指定(0~6)を行うと,想定外の値が入ってしまったらエラーになる.
列挙型に指定することで範囲チェックも指定できる.
複雑な列挙型
フィールド,メソッド及びprivate
コンストラクタを含めることができる.
列挙型のコンストラクタはprivate
でなければならない
インタフェース
OOPにおけるポリモフィズム
- 同じ操作(メソッド実行)に対して,オブジェクト毎に異なる動作を行わせる仕組み.
但し,操作に対して得られる結果の種類(型)は同じ. - 多様性,多態性ともいい,モジュール間の疎結合化に活用
- Java言語ではインタフェースを活用してポリモフィズムを実現することが多い.
インタフェースとは部品同士を繋ぐための「規格」
- 部品化には部品同士を繋ぐための「規格」が必要
- 規格がなければ部品同士を組み合わせることは困難
- また,その規格は極力下記の要件を満たす必要がある
「すぐ装着できる」「すぐ取り外しできる」「装着,取り外しには相互の部品には影響がない」
Javaのインタフェース
- 「
interface
」句で定義して,public
の抽象メソッドを定義 - インタフェースで定義した抽象メソッドには暗黙的に
public abstract
句がつけられる - フィールドも定義可能だが,暗黙的に
public static final
となり,実質的に「定数」になる - 実装クラスは「
implements
インタフェース名」を指定し,全ての抽象メソッドを実装する必要有 - インタフェースはインタフェースの拡張可能
- 1クラスがクラス拡張とインタフェースの実装を行うことも可能(
class C extends A implements B
) - 1クラスが複数インタフェースを実装可能(
class C implements A, B
)
密結合・疎結合
- インタフェースを活用したポリモフィズムの活用により,実装クラス利用側は
実装クラス内部の詳細を把握する必要がないため, クラス間の依存度,結合度を低下させることができる. - しかし,実装クラスの利用側が実装クラスの名前を明示的に指定して
new
演算子でオブジェクトを
生成していると, 結局は実装クラス使用側と実装クラスの結びつきが残存してしまう. この場合,使用する実装クラスを変更する場合に実装クラス利用側も変更する必要が出てくる.
インタフェースを活用したポリモフィズムを活用する場合,
実装クラス利用側で直接的に実装クラス名を指定してオブジェクトを生成せず,
下記のような方法で間接的に生成する方が,よりクラス間の結び付きを緩やかにできる.- Factoryクラス(GoFのFactory Method Pattern)
[TODO: あとでFactory Method Patternの記事をまとめる] - JNDI(Java Naming and Directory Interface)
- CDI(Context Dependency Injection)
- Factoryクラス(GoFのFactory Method Pattern)
Java SE 8 のインタフェースの新機能
Java SE 7 までのインタフェース
抽象メソッドと定義フィールドのみ定義可能
Java SE 8 以降のインタフェース
- 新機能として
default
メソッドとstatic
メソッドをサポート - インタフェース内で実装を定義することが可能になった
→ インタフェースとその実装クラスの機能拡張が行いやすくなった
defaultメソッドのルール
- インタフェースとスーパークラスで同一シグネチャのメソッドがある場合,
サブクラスではスーパークラスのメソッドが使用される - インタフェースとサブタイプのインタフェースで同一シグネチャのメソッドがある場合,
実装クラスではサブタイプのメソッドが使用される - 同一シグネチャのメソッドを持つインタフェースをクラス多重実装する場合,
そのクラスで同じメソッドを実装する必要がある.
ラムダ式
ラムダ式とは
関数のこと.または名前のない関数を指す場合がある.SE8から導入.
関数ってなに?
特定のパラメタに対して特定の処理を行い,特定の結果を出す.
関数が処理を行う際,他の何に対しても影響しないし,影響されない → 独立性の高い部品
ラムダ式(関数)とは?
ラムダの基本文法
過去記事参照.
ラムダ式の型
- ラムダ式にも型がある
- MyFunc型というインタフェースをつくる.MyFunc型のラムダ式を参照変数fに格納
MyFunc f = a -> "Hello!" + a;
fには,関数の「定義」が格納されている.
関数実行後の「結果」が格納されているわけではない.
関数型インタフェース
ラムダ式の型は,関数型インタフェースと呼ばれる
関数型インタフェースは抽象メソッドを1つだけもつインタフェースのこと
- 抽象メソッドは必ず1つだけ
staticメソッド
やdefault
メソッドも存在してよいjava.lang.Object
クラスのpublic
メソッドもオーバーライド可能@FunctionalInterface
アノテーションをつけると抽象メソッドが1つしかないことを
コンパイル時にチェック可能(必須ではない)
これも過去記事にまとめ済み.