OCJP Gold SE8へアップグレードした
Upgrade Java SE 7 to Java SE 8 OCP Programmer(1Z0-810)に合格した。
OCJP Gold SE7から同SE8への移行試験だったので、純粋なOCJP Gold SE8の試験(1Z0-809)とは内容が異なる。
点数は66点だった。(※合格点は65点)前回のSE7試験の時と同様に、超ギリギリだった。
なので今回も感想文もとい反省文を書く。
【試験】
Upgrade Java SE 7 to Java SE 8 OCP Programmer | Oracle Certification Exam
移行試験は公式*1でも言われている通り、ラムダまつりだった。
試験の8~9割はラムダ式とStreamAPIで占められており、たまにDate and Time APIが出現する問題構成だった。
【勉強方法】
1Z0-809試験に対応する英語の参考書は存在するが、1Z0-810試験に対応した参考書が日本語英語ともに存在しないという状態だった。(2016/5月時点)
1Z0-809用の参考書も検討したが、ラムダ式・StreamAPIの分量が少なく、また内容も基礎的な部分のみ試験対象とされていたので、参考書は使用せずWeb上の情報を中心に勉強を進めた。
【使用した教材 Web】
1.Exam 1Z0-810: Upgrade Java SE 7 to Java SE 8 OCP Programmer Study Guide
java.boot.by
初めは記述内容が合っているか不安だったが、記述内容は正確だった。*2
1Z0-810試験の試験項目に合わせた章立てとなっている。
各単元ごとに参照先のページが示されていたので、そこから一次情報を追うことができた。Oracle Tutorialからの引用が多かった印象。
docs.oracle.com
出典のページが最後にまとめられていたのが便利だった。
Bibliography
勉強手順としては、読む→サンプルコード写経→和訳してブログに書く という手順を繰り返した。
途中で和訳がしんどくなったので、読む→サンプルコード写経→大事そうな部分をメモる という手順に変えたが、効果はあったと感じている。
特にCollectionの辺りは他の方のブログやサイトのコードも写経した。
Javaラムダ式メモ(Hishidama's Java8 Lambda Expression Memo)
2.MyExamCloud
1Z0-810 OCPJP 8 Upgrade Practice Mock Exam 1 MyExamCloud online exam
IT系資格の模擬試験を提供するサイト。
「Time Offer(50% Discount)」などと書かれており、非常にうさんくさい。しかし無料の模擬試験を受けたところ、割といい感じと思えたので、「1Z0-810 OCPJP 8 Upgrade Practice Mock Exam 1~5」 を購入した。*3
難易度的には本番より少し易しめ~同程度だが、試験的中率はそこまで高くなかった印象*4。ただ、試験問題の雰囲気をつかむことはできる。
3.その他よく参照した資料
Java 8:ラムダ式、パート1
Java Magazineのラムダ式解説。ラムダ式の必要性の部分から解説されている。
Java7→Java8アップグレードに成功・・・ - M12i.
先人の合格記。
必修! Date and Time API──Java SE 8の新日時APIの基本を学ぶ - builder by ZDNet Japan
Date and Time APIの基礎
Java SE 8のストリームAPIの正しい使い方──ラムダ式とともに導入された新APIで、並列処理の実装はどう変わるのか? - builder by ZDNet Japan
Parallel Stream周り
StreamAPIのおさらい - java.util.stream.Stream - ITお絵かき修行
StreamAPIの各メソッドを覚えるのに使用した。
4.受ける前に見ておきたかった資料
自分の受験後に見つけた、Oracle Universityより公開された資料。
http://www.oracle.co.jp/jdt2016/pdf/HO-1.pdf
Java Day Tokyo 2016での試験対策セッション資料。非常にわかりやすく、練習問題も本番の感じに近い。
Oracle Certified Java Programmer, Gold SE 8 認定資格移行試験(1Z0-810)対 策ポイント解説セミナー(1) - YouTube
Oracle Certified Java Programmer, Gold SE 8 認定資格移行試験(1Z0-810)対 策ポイント解説セミナー(2) - YouTube
1Z0-810試験対策セミナー動画。これで睡眠学習ができる。
【使用した教材 書籍】
1.『現場で使える[最新]Java SE 7/8 速攻入門』
- 作者: 櫻庭祐一
- 出版社/メーカー: 技術評論社
- 発売日: 2015/11/19
- メディア: 大型本
- この商品を含むブログ (1件) を見る
英語の情報をあたっているときに意味不明な箇所が出てきたら辞書的に引く、という使い方をした。この1冊を覚えるだけでも十分かもしれない。
Date and Time APIについては、日本語書籍の中では一番詳しく解説されていると思う。ただしアメリカの夏時間の取り扱いなど、微妙に触れきれていない部分もあるので、Web上の情報も併用して試験対策にあたった方が良いと思われる。
【試験の感想】
・Map、List、Collectionクラスに追加された新規メソッドはどれ?や正しい使い方はどれ?といった問題に苦戦した。
・内部クラス、無名内部クラス系の変数のスコープ問題にも苦戦した。
・StreamとIntStream、LongStreamなどのプリミティブなデータ型を使うStreamとの違い、はそもそもほとんど覚えられていなかった。
・Instant、Period、Durationはネット上でも積極的に取り上げている人が少なく、APIの利用方法を問われると弱かった。(さらにLocalDate、LocalDateTimeの違いや夏時間の計算、各種定数クラスを絡められたので非常にとてもつらかった)
【総括】
・非常にしんどかった。1回目の受験で合格できたが、落ちてたら挫折していたと思う。。
・全体的に間違いが多かったので、集合に対する操作にはラムダ式を意識してソースを書くよう心掛ける。
→試験のおかげで、関数に対する心理的な障壁はかなり無くなった、と感じている。
AWS Summit Tokyo 2016メモ【The State of The Art - AWS / EC2 Networking (同時通訳)】
AWS Summit Tokyo 2016に参加した。
下記セッションに参加したので、参加メモを書いておく。
※正確な情報・見解は後日公開される(であろう)登壇者のスライドや公式資料等を参照のこと。
www.awssummit.tokyo
The State of The Art - AWS / EC2 Networking (同時通訳)]
Kevin Miller (Director, Software Development, EC2 Networking, Amazon Web Services, Inc.)
【概要】
EC2における、LinuxカーネルレベルでのTCPネットワークパラメータチューニングの話。
AWS,EC2に拘った内容というよりは、Linux全般でのTCPチューニングの話だった。
とにかく話が早くあっという間に終わった。
【内容】
①TCPの性能
・TCPはSSH、HTTP等のベースプロトコルであり、送信側と受信側それぞれが互いに接続しあう。
・TCPの特徴として、異なる大きさの送信/受信ウィンドウを持つ。
・輻輳制御ウィンドウ:送信側が制御する。輻輳制御アルゴリズムで制御する。
・パケットの損失(パケットロス)がスループットに与える影響について触れていた。
TCPの統計値取得 :netstat -s | grep retransit
ソケットレベルの診断:ss -ite
・パケットの再送状況をリアルタイムに取得できるコマンドがgithub上にあるとのこと。詳しくは下記を参照。
github.com
・Linuxの輻輳制御アルゴリズム
1.BIC (Linux2.6.6~2.6.18)
2.CUBIC(Linux2.6.19以降)
→TCP Renoに代わるアルゴリズム。
・再送タイマー
パケットロスした、とみなす時間の設定。
短すぎると:過剰反応してしまい、パフォーマンスが落ちる。
長すぎると:パケットロスの検知が遅れ、パフォーマンスが落ちる。
デフォルトは200ミリ秒。
・ip route list
AWSの場合、サブネット内の他のインスタンスへルーティングしている場合があるので、そこの再送時間の設定を変える。(例えば10ミリ秒にする等)
・ネットワークパスのチューニング
パス上のルータにネットワークバッファがある。
→NWへの負荷が高まると、再送が多くなり、結果としてタイムアウトを引き起こす原因となる。
・ネットワークバッファのアクティブキュー管理
→tc qdisc list
・fq_codel
→チューニングが不要な、qdiscのアルゴリズム。
・EC2拡張NW機能
EC2で提供するAmazonLinux,Windows(WindowsServer?)に組み込まれたドライバにて利用することができる。詳しくは下記を参照。
www.youtube.com
・MTU
Maximum Transmission Unit (MTU)は、ネットワークにおいて1回の転送(1フレーム)で送信できるデータの最大値を示す伝送単位のこと。
Maximum Transmission Unit - Wikipedia
多くのドライバは1500バイトを設定することができる。しかし上記の「EC2拡張NW機能」のドライバを使うと9000バイトまで設定することができる。よってオーバヘッドを減らすことができる。
→MTUの設定値は「ip route list」から確認することができる。
②応用
実際に上記で取り上げた要素を使って、測定を行った結果を紹介していた。
JavaDayTokyo2016メモ【3-E: Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか】
JavaDayTokyo2016に参加した。
下記セッションに参加したので、参加メモを書いておく。
www.oracle.co.jp
[3-E: Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか]
TIS株式会社
アプリケーション開発センター シニアエキスパート
川島 義隆 氏
【概要】
Java9で追加された新機能を使った設計・実装の紹介
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
【内容】
1.nullチェック
・Optionalクラスを使いましょう、という話。
・Optionalクラスの使い方としては、nullが発生しうる実装個所を包み込むように実装すべき。
→Javaの個々のAPIはnullチェックを意識した戻り値となっていないので、
Optionalを使ってAPI単位でのnullチェックを行うべき。
2.Mixin
mixin とはオブジェクト指向プログラミング言語において、サブクラスによって継承されることにより機能を提供し、単体で動作することを意図しないクラスである。
Mixin - Wikipedia
・Javaは多重継承が認められていない。そのため、ミドルウェアパターンの実装を行う場合は、ミドルウェアに対応するサブクラスを実装する。(例:ResultSet)
・Javaでミドルウェアパターンを実装するときは、事前に(※I/F側に)多くのメソッドを予め用意しておく場合が多い。
・Java8以降ではI/Fにデフォルトメソッドを持つことが可能となったので、共通的な実装をI/F側で持つことができるようになった。
→ただし状態を持つことはできないので、デフォルトメソッド内からI/Fの別メソッドを参照するような実装をしておき、実装クラス側からオブジェクトを渡すよう強制する、といった方法をとることができる。
・動的mixinの方法として、MethodHandleというクラスがJava7から追加された。
→ただし従来のリフレクションの10~100倍遅い。
3.システム挙動の動的な変更(using REPL)
・アプリケーションに管理用APIを用意するには、という話。
・enkanというFWでは疑似REPLが用意されており、REPLからMWの状態を変更することが可能。
→enkanではJShellを取り込む、とのこと。
4.Java9時代の無停止デプロイ
●従来
①LBでサーバごと切り替え
→問題点:サーバが2台ないし3台必要。
②APサーバ(コンテナ)で対応
→問題点:メモリリーク
●これから
JVMのプロセス単位で切り替え
・SO_REUSEPORT((Linux kernel 3.9~より利用可能。同じuidから利用可。Windowsでは不可)という仕組みを利用して、同一ポートに対してリッスンするプロセスを複数立ち上げる。
・SO_REUSEPORTの利用には、ServerSocketChannelクラスのメソッドを実装したAPサーバが必要。現状だとJettyくらいしか選択肢がない。
・falchion-containerというJVMプロセスをプールするコンテナを作られたそう。
→JMX・JStatで監視。
JavaDayTokyo2016メモ【2-A: Project Jigsawではじめるモジュール開発】
JavaDayTokyo2016に参加した。
下記セッションに参加したので、参加メモを書いておく。
※正確な情報・見解は後日公開される(であろう)登壇者のスライドや公式資料等を参照のこと。
www.oracle.co.jp
[2-A: Project Jigsawではじめるモジュール開発]
Java in the Box 櫻庭 祐一 氏
【概要】
Project Jigsawの導入背景、モジュールの作成方法・使用方法の紹介
【内容】
1.導入背景
(1)現状
・現在のJavaには「クラスパスが複雑」「rt.jarの肥大化」という2つの課題を抱えている。
・上記に関連し、「JAR HELL」と呼ばれるような.jarファイル間の依存関係の複雑さも発生している。
(2)(1)の原因
・クラスパス・JARのパッケージング機構における、
「依存関係」「バージョン」「公開範囲」をコントロールする仕組みが不足しているため。
・特にクラスのpublic属性のアクセス範囲が広すぎることが大きな原因とみられている。
→『public is TOO public』
(3)歴史
・2005年頃から提言はされていた。
・JSR277、JSR294といったJSRを経てProject Jigsawが発足し、Java9で採用。
2.モジュールの作成
・モジュールを作成する際の定義内容は以下の3要素。
Module extends JAR{ dependency …「依存関係」 export …「公開範囲」 version …「バージョン」 ※バージョンに対応する仕組みはまだない。今後どうなるか不明とのこと。 }
・モジュールはJARの拡張。JARと同じくクラスパスに追加しクラスを読み込ませることは可能。
・今までのpublicクラスは誰からでもアクセス可能だった。これからの(※モジュール内の)publicクラスは、公開範囲に対応するクラスからしかアクセスできなくなる。
→今後はmainメソッドを含むクラスを明示的に公開しないと、アプリが起動できなくなる。
・モジュールの定義内容は「modules-info.java」に記述する。「modules-info.java」は「src」フォルダ直下に置く。(※読み込み効率、複数ファイル対応etcの為)
例:modules-info.java
module fxdemo { requires javafx.controls; requires javafx.graphics; }
3.モジュールの使用
(1)コンパイル
・jarコマンドに「--create」などのオプションを付与して実行する。tarっぽいらしい。
(2)実行
・実行時はオプションを指定して実行する。
「モジュールのみ使用」「モジュールとクラスパス」といった使い方が可能。
例:実行コマンドの先頭部
java -mp mods -addmods ・・・
・mainメソッドの実行コマンドは「モジュール名/クラス名」となる。
Upgrade Java SE 7 to Java SE 8 OCP Programmer(1Z0-810)対策 第三章 ラムダ式を使用するコレクション(1)
第三章よりラムダ式を使用したstreamに対するフィルタリングを取り扱う。
■注意
正確な情報は下記リンクを参照してください。
■試験対策ページ
java.boot.by
■試験
Upgrade Java SE 7 to Java SE 8 OCP Programmer | Oracle Certification Exam
3.1. forEach()メソッドとメソッド・チェーンを使用したコレクションの反復処理
繰り返し処理を制御するイテレータには一般的に2つの実装アプローチが存在する。
Activeな(外部)イテレータ
Activeなイテレータでは、イテレータの制御者が、次の要素へ処理が移ったことを伝えたり、各要素へアクセスした際に処理を行ったり等、制御者自身が生成した繰り返し処理を細かく制御できる。
Java1.0、1.1ではVectorとHashtableというコレクションクラスと、Iteratorデザインパターンを実装したEnumrationと呼ばれるクラスがあった。
Vector names = new Vector(); names.add("George"); names.add("Fred"); names.add("Ron"); Enumeration e = names.elements(); while (e.hasMoreElements()) { String name = (String) e.nextElement(); System.out.println(name); }
Java1.2ではIteratorデザインパターンはIteratorというクラスに実装された。Iteratorでは未だに返却値のキャストが必要とされていた。Java1.2から1.4にかけて文字列の繰り返し処理はは下記のようなコードだった。
List names = new ArrayList(); names.add("George"); names.add("Fred"); names.add("Ron"); Iterator i = names.iterator(); while (i.hasNext()) { String name = (String) i.next(); System.out.println(name); }
Java5ではジェネリクスが導入され、Iteratorインタフェースクラスとforループの実装が改修された。
// Java SE 5 !!! package java.lang; import java.util.Iterator; public interface Iterable<T> { public Iterator<T> iterator(); }
package java.util; public interface Iterator<E> { public boolean hasNext(); public E next(); public void remove(); }
メモ:forループの内部では Iterator.hasNext() と Iterator.next()が呼ばれている。そのためActiveなイテレータとみなす事ができる。
List<String> names = new ArrayList<String>(); names.add("George"); names.add("Fred"); names.add("Ron"); for (String name : names) { System.out.println(name); }
Passiveな(内部)イテレータ
Passiveなイテレータではイテレータ自身が繰り返し処理を制御する。イテレータの制御者は基本的に、コレクション内の要素に対するいくつかの操作をイテレータに行うよう指示します。Java8ではこのアプローチが利用可能である。
Java8ではjava.lang.IterableインタフェースクラスがforEachメソッドを持つ
package java.lang; import java.util.Iterator; import java.util.function.Consumer; public interface Iterable<T extends Object> { public Iterator<T> iterator(); public default void forEach(Consumer<? super T> cnsmr) { // ... } ... }
java.util.Collectionインタフェースクラスはjava.lang.Iterableクラスを継承している。そのためjava.util.List もしくは java.util.Setインタフェースクラスの実装クラスは自動的にforEachメソッドを持っている。
java.util.Mapインタフェースクラスはjava.util.Collectionインタフェースクラスを継承していない。しかしJava8からは一貫性のためにforEachメソッドを持つ。
このメソッドはひとつのパラメータをとる関数型インタフェースである。そのため実体のパラメータを通すforEachメソッドはラムダ式の候補となる。
List<String> names = new ArrayList<>(); names.add("George"); names.add("Fred"); names.add("Ron"); names.forEach(name -> System.out.println(name));
もしくはメソッド参照を使用する。
... names.forEach(System.out::println); ...
上記のPassiveなイテレータと前セクションのActiveなイテレータとの差異を述べる。
Activeなイテレータのリスティング処理では、イテレーションのループ構造がイテレーションを制御し、ループを通過する度にループ内のオブジェクトはリストより回収され、文字列を出力する。
Passiveなイテレータのリスティング処理では、明確なループ処理は存在しない。単純に、リスト内におけるオブジェクトの処理(─今回の場合は単純な文字列の出力)をforEachメソッドにて呼び出す。
イテレーションの制御はforEachメソッドに依存する。
java.util.ListクラスにおけるforEachメソッドのシグネチャ
package java.util; public interface List<E extends Object> extends Collection<E> { /** * Performs the given action for each element of the Iterable until all elements have been * processed or the action throws an exception. */ public default void forEach(Consumer<? super T> cnsmr) { ... } ... }
java.util.SetインタフェースクラスにおけるforEachメソッドのシグネチャ
package java.util; public interface Set<E extends Object> extends Collection<E> { /** * Performs the given action for each element of the Iterable until all elements have been * processed or the action throws an exception. */ public default void forEach(Consumer<? super T> cnsmr) { ... } ... }
java.util.MapインタフェースクラスにおけるforEachメソッドのシグネチャ
package java.util; public interface Map<K extends Object, V extends Object> { /** * Performs the given action for each entry in this map until all entries have * been processed or the action throws an exception. */ public default void forEach(BiConsumer<? super K, ? super V> bc) { ... } ... }
Upgrade Java SE 7 to Java SE 8 OCP Programmer(1Z0-810)対策 第二章 ラムダ式を使用する事前定義済みの型の使用
第二章よりJava8で追加された関数型インタフェースの各クラス、メソッドの仕様を追っていく。
各インタフェースの詳細まで追うのは辛いので取り扱わない…
■注意
正確な情報は下記リンクを参照してください。
■試験対策ページ
java.boot.by
■試験
Upgrade Java SE 7 to Java SE 8 OCP Programmer | Oracle Certification Exam
2.1. java.util.function パッケージのインタフェースについて説明する
多くの再利用可能な機能要件について、関数型インタフェースとラムダ式は取り込むことができる。
Java8の設計者は一般的なユースケースを取り込み、それらのためのライブラリを実装した。
java.util.functionと呼ばれる新しいパッケージは、一般的なユースケースに対する機能を提供する。
※WARNING※
このセクションで提示するインタフェースのリストは完全ではない。最も重要な部分の関数型メソッドのシグネチャのみ列挙する。
java.util.function.Predicate
パラメータの型: T
戻り値の型 : boolean
メソッドの詳細: 1つの引数の述語(boolean値関数)を表す。
package java.util.function; @FunctionalInterface public interface Predicate<T extends Object> { public boolean test(T t); }
java.util.function.Consumer
パラメータの型: T
戻り値の型 : void
メソッドの詳細: 単一の入力引数を受け取って結果を返さないオペレーションを表す。
package java.util.function; @FunctionalInterface public interface Consumer<T extends Object> { public void accept(T t); }
java.util.function.Function
パラメータの型: T
戻り値の型 : R
メソッドの詳細: 1つの引数を受け取って結果を生成する関数を表す。
package java.util.function; @FunctionalInterface public interface Function<T extends Object, R extends Object> { public R apply(T t); }
java.util.function.Supplier
パラメータの型: (なし)
戻り値の型 : T
メソッドの詳細: 結果のサプライヤを表す。サプライヤを呼び出すたびに新規もしくは異なる結果が返される必要はない。
package java.util.function; @FunctionalInterface public interface Supplier<T extends Object> { public T get(); }
java.util.function.ToDoubleFunction
パラメータの型: T
戻り値の型 : double
メソッドの詳細: double値の結果を生成する関数を表す。これは、Functionに対して、doubleを生成するようプリミティブ化を行ったもの。
package java.util.function; @FunctionalInterface public interface ToDoubleFunction<T extends Object> { public double applyAsDouble(T t); }
java.util.function.BiPredicate
パラメータの型: T,U
戻り値の型 : boolean
メソッドの詳細: 2つの引数の述語(boolean値関数)を表す。これは、Predicateを引数を2個取るようにしたもの。
package java.util.function; @FunctionalInterface public interface BiPredicate<T extends Object, U extends Object> { public boolean test(T t, U u); }
java.util.function.UnaryOperator
パラメータの型: T
戻り値の型 : T
メソッドの詳細: 単一のオペランドに対する操作に作用して同じ型の結果を生成する演算を表す。これは、オペランドと結果の型が同じである場合においてFunctionを特殊化したもの。
メモ:Functionクラスを拡張しており、Function.apply(Object)メソッドを引き継いでいる。
package java.util.function; @FunctionalInterface public interface UnaryOperator<T extends Object> extends Function<T, T> { }
Upgrade Java SE 7 to Java SE 8 OCP Programmer(1Z0-810)対策 第一章 ラムダ式(3)
(1)(2)に引き続き、ラムダ式の章を進める。
■試験対策ページ
java.boot.by
■注意
全文が超意訳です。正確な情報は下記リンクを参照してください。
■試験
Upgrade Java SE 7 to Java SE 8 OCP Programmer | Oracle Certification Exam
1.3. ラムダ式について説明する 匿名インナークラスを使用したコードをラムダ式を使用するようにリファクタリングする 型推論とターゲット型付けについて説明する
匿名インナークラスとラムダ式で置き換える
開発者のコードの一部には無名インナークラスが含まれており、時として読みづらい。
開発者は匿名インナークラスを、読みやすさとメンテナンスしやすさのために置き換えるべきである。
匿名インナークラスとラムダ式での置き換えによって、定型化したコードの何行かのコードを書くよりも開発時間を短縮できるだろう。
一般的なSwingアプリケーションでは匿名インナークラスをアプリケーションに機能追加する際に必要とする。
例えば匿名クラスはボタンにactionを追加するよく使われる方法である。ここでの問題は内部クラスは読みにくいということであり、多くの定型化したコードを書く必要があることである。
下記のコードはボタンのactionの実装として匿名インナークラスの実装を試している。
まずは下記のラムダ式で置き換える前のコードを見てほしい。
JButton button = ... JLabel comp = ... button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { comp.setText("Button has been clicked"); } });
例えばActionListenerインタフェースクラスの具象クラスを実装する。このインタフェースはactionPerformedという1つのメソッドを保持している。
actionPerformedメソッドはユーザーが実際に画面上のボタンを押下した時に、buttonインスタンスより呼び出されている。
匿名インナークラスはメソッドの実装を提供する。
匿名インナークラスはJavaプログラマーがコード内でデータを受け渡しやすいように設計されている。
だが不幸なことに、それらはコードをわかりにくくしている。ここでは1行の重要なコードを呼び出すために4行の定型化されたコードが必要となる。
定型化されたコードの問題は1つではない。このコードは開発者の意図が明確でなく非常に読みづらい。
開発者が行いたいことはいくつかの振る舞いを実行するすることであり、(メソッドに)オブジェクトを渡したくない。
Java8ではこのコードをラムダ式で書くことができる。下記にサンプルを示す。
JButton button = ... JLabel comp = ... button.addActionListener(e -> comp.setText("Button has been clicked"));
・インタフェースを実装したオブジェクトを渡す代わりに、匿名の関数(ブロック化されたコード)を渡している。
・"e"(Javaの修飾子名以外が指定可能)は匿名インナークラスのパラメータのようなパラメータである。
・"->"はラムダ式の関数部からパラメータを分離する。ユーザがボタンをクリックした際に動作する。
・他の匿名インナークラスを使用していたときとの違いは変数eの宣言である。以前は明確に ActionEvent e と型を宣言していた。
今回の例(※ラムダ式を使った場合)開発者に型となるクラスが渡されていないが、このクラスはコンパイルすることができる。
内部で何が起こっているかというと、変数eに対してaddActionListenerメソッドのシグネチャより型推論が行われている。
これは、開発者は明確にパラメータの型を記述する必要がないということを意味する。
※WARNING※
いくつかの場面ではJavaコンパイラが型を推論できない場合、変数の型やパラメータの型を明確に記述する必要がある。
下記の例はラムダ式の引数に対して、明示的に型を記述する場合。
JButton button = ... JLabel comp = ... button.addActionListener((ActionEvent e) -> comp.setText("Button has been clicked"));
- 括弧で囲まれたカンマ区切りのリスト
メモ:ラムダ式のパラメータの型は省略することができる。加えて、パラメータがひとつの場合は括弧を省略することができる。例えば下記のラムダ式は正しい。
s -> s.getAge() >= 18
(Student s) -> s.getAge() >= 18
(s) -> s.getAge() >= 18
- アロー演算子
- メソッド本文は「1つの式」もしくは「ブロック」から構成される。
... -> s.getAge() >= 18
1つの式しか記述しない場合、Javaの実行環境は式を戻り値の評価を行う。代わりに「return」句を使うことができる。
... -> { return s.getAge() >= 18; }
return句に型はない。ラムダ式では、式を中括弧{}で囲む必要がある。しかし、voidメソッドは中括弧で囲む必要はない。例えば、下記のラムダ式は正しい。
email -> System.out.println(email)