半年ぶりのblog更新の季節がやってきました。春と秋はJavaのアップデートの季節です。16がリリースされます。17の1つ前のバージョンということがあり、いろいろと機能盛りだくさんです。16で入れておかなくてはいけないわけです。17で正式な機能にならないと、3年後になってしまいますから。残念なのはswitch式でのパターンマッチが結局入らなかったことでしょうか。instanceofのパターンマッチは使えるのですが、本命はswitch式の方なので。16で取り入れられるJEPは16個。14の採用なども含まれているので、Javaの機能としては13個のJEPです。16ではAPIの変更が多いというのも特徴的です。Panama関連で3つのJEP、それ以外にもUnixドメインソケットのJEPと、4つもAPIに関するJEPがあります。こんなにAPIに関するJEPがあったのは、JEPのプロセスになってからはじめてのような気がします。JEPにはなっていないのですが、それ以外にも大きなAPIの変更があります。いうことで、ここ数年でAPIの変更が最も大きいバージョンになりそうです。Panama関連のAPIの追加はIncubatorであり、規模も大きいので、このエントリーでは省略させていただきます。いつものようにセキュリティ系のAPIはちゃんと理解していないので、省略します。16で廃止されたAPIは1つだけです。14でforRemoval=trueになったコンストラクタが1つだけ削除されました。javax.tools.ToolProvider()ToolProviderクラスはコンパイラなどを取得するために使用するクラスですが、メソッドはすべてstaticメソッドで、インスタンスを生成する必要がないため、削除されました。正式なAPIの廃止はこれだけなのですが、Preview機能に関するメソッド廃止というか変更もありました。それは、APIの追加のところで説明します。Classesに関連するものが多いです。Classのコンストラクタを廃止予定にし、使用時に警告を出すというものです。Valhallaに関連したJEPになります。ちなみに、ラッパークラスのコンストラクタはすでに@Deprecatedだったのですが、foreRemovale=trueが追加されたということです。s)java.net.URLDecoder()javax.management.relation.RoleStatus()ThreadGroupクラスはresumeメソッドやsuspendメソッドはすでにforRemovalがtrueになっていましたが、それに追加してdestroyメソッドなどが廃止予定に追加されています。AWTの3つのメソッドはいずれもファイナライザーなので、使わない方がいいということは分かっていいので、標準ライブラリでも削除予定になっているわけです。16ではこれ以外にjava.desktopモジュールなどでもAPIの追加が行われています。11以降で追加されたAPIはほとんどが言語仕様に関連したものが多く、一般の開発者が使うことがないようなAPIばかりでした。16では久しぶりによく使いそうなメソッドが追加されています。APIなどについてはじめに紹介して、その後はいつも通りモジュール/パッケージのアルファベット順に紹介していきます。APIでは、プリミティブ系のStreamに1つ、Streamインタフェースには2種類のメソッドが追加されました。これにともなって、3つの内部インタフェースが追加されています。StreamインタフェースStreamインタフェースでは2種類のメソッドが追加されたと書きましたが、4つは関連したメソッドで総数としては5つのメソッドが追加されました。toList()いずれもdefaultメソッドです。インタフェースへのメソッド追加なので、そうならざるをえないわけですね。戻り値を見ていただければ分かる通り、mapMulti系が中間操作、toListメソッドが終端操作です。mapMultiメソッドの引数はBiConsumerインタフェースですが、これは引数が2つ、戻り値なしの関数型インタフェースです。中間操作なのに、戻り値がないというのはどういうことなんでしょう。いう動作をするのかはソースを見てもらうのが手っ取り早いでしょう。}mapMultiメソッドの引数のBiConsumerインタフェースは引数が2つですが、一方はストリームを流れてくる値、もう一方がConsumerオブジェクトです。このConsumerオブジェクトが上記のソースだと変数bufferで表されるSpinedBufferオブジェクトです。このSpinedBufferクラスはBufferという名前がつくように何らかのバッファだと考えられます。SpinedBufferクラスのacceptメソッドでバッファに要素を追加していきます。StreamSupportクラスのstreamメソッドでバッファの要素をストリーム化しているわけです。いうことで、BiConsumerインタフェースのラムダ式では、流れてきた要素に対し何らかの処理を行い、必要であれば第2引数のConsumerオブジェクトの顔をしたバッファに要素を追加していきます。すると、次の処理にはConsumerオブジェクトに追加した要素が流れてくることになります。単純に条件に合致した要素だけを取り出す例で考えてみましょう。以下のコードは10以下の数だけを集める処理です。この例だとfilterメソッドを使ったのと変わりないですが、ストリームの要素がバラバラで統一的に処理できないような時に使うことができるはずです。mapMulti系の他の3つのメソッドはいずれもプリミティブ系のストリームに変更する場合に使用するもので、使い方としてはmapMultiメソッドと同じです。最後のtoListメソッドはストリームをリストに変換するメソッドです。単純ですが、使用機会はとても多いはずです。実施的には、collectメソッドにCollectors.toList()を引数にした場合と同じ動作です。これも実装を見てみましょう。}Collectors.toListメソッドではなく、toArrayメソッドを使って変更不可能なリストを作成しています。IntStream/LongStream/DoubleStreamインタフェースプリミティブ系のストリームにもmapMultiメソッドが追加されています。BiConsumerインタフェースに対応するように内部インタフェースがそれぞれ追加されています。IntStream.IntMapMultiConsumerLongStream.LongMapMultiConsumerDoubleStream.DoubleMapMultiConsumerjava.base/java.netパッケージまさかのjava.netパッケージにクラスが追加されましたよ。Channelsに関連したクラスです。UnixDomainSocketAddressクラスUnixドメインソケットは同一PC内でのプロセス間通信を行う時に、高効率で通信できるソケットです。JavaではTCP/IP通信と同じように扱うことができます。違いはアドレスを表すクラス、つまりこのUnixDomainSocketAddressクラスだけです。UnixDomainSocketAddressクラスは、InetSocketAddressクラスと同様にSocketAddressクラスのサブクラスです。Unixドメインソケットではファイルパスで指定して通信します。このため、UnixDomainSocketAddressクラスもインスタンシーエションはファイルパスで行います。UnixDomainSocketAddress.of(Path.of("tmp/socketfile2"));ofメソッドは引数がStringクラスとPathインタフェースの2種類があります。UnixDomainSocketAddressオブジェクトが生成できれば、後はTCP/IP通信と同様にSocketChannelなどで使用できます。StandardProtocolFamily列挙型Unixドメインソケットが追加されたので、StardardProtocolFamily列挙型にも定数が追加されました。UNIX通常は、この列挙型を使うことはほぼないはずです。java.base/java.nioパッケージBuffer系のクラスにメソッドが追加されました。いずれも同じメソッドなのですが、引数の型がそれぞれ異なります。ByteBuffer/CharBuffer/ShortBuffer/IntBuffer/LongBuffer/FloatBuffer/DoubleBufferクラスいずれのクラスもputメソッドのオーバーロードが追加されています。以下にはByteBufferクラスの場合のシグネチャを示します。src)メソッドはありました。書き込み位置と範囲を指定できるputメソッドがなかったのです。ByteBufferクラスだけを引数にして、適切なpositionとlimitを設定しておけば、同じ動作はできるんですけどね。分かりやすさを優先させたんでしょう。java.base/java.langパッケージここからはそれほど使わないであろうAPIの変更をアルファベット順に説明していきます。java.langパッケージですが、こちらはJEP関連のメソッド変更がありました。Classes関連のAPI変更がありました。変更というのは名前とシグネチャが変わったということです。15で導入されたpermittedSubclassesメソッドは廃止されました。この2つのメソッドの違いは戻り値の型です。permittedSubclassesメソッドはClassDesc[]だったのが、getPermittedSubclassesメソッドではClass[]になっています。当然のことながら使いやすいのは、ClassDescクラスよりもClassクラスということだったのでしょう。IndexOutOfBoundsException例外コンストラクタが1つ追加されました。index)indexがintのコンストラクタはあったのですが、longはありませんでした。いうか、配列のインデックスはintだけなので、配列を想定していたらlongは必要なかったわけです。配列のインデックスがlongになることはないでしょうけど、Bufferとかはlongのインデックスがほしいと思うことはちょっとあります。Classに関するAPIが追加されています。MethodHandlesクラスMethodHandlesクラスはIndyでメソッドをコールするために使用するMethodHandleクラスのユーティリティクラスです。そんなMethodHandlesクラスにメソッドが2つ追加されました。index)どちらもIndyがはじめてコールされた時に使用されるブートストラップメソッドからコールされることを想定しています。簡単に言うと、引数のLookupオブジェクトから第3引数で指定されたクラスを返すというメソッドです。Classを作成した時を想定しています。普通は使うことはないでしょうね。MethodHandles.LookupクラスLookupクラスはindyやcondyでメソッドなどをルックアップするためのfindXXXメソッドを定義しています。15でdefineHiddenClassメソッドが追加されました。これに関連して、もう1つメソッドが追加されました。他にラムダ式のように動的に生成したクラスを定義するためにdefineClassメソッドなどがあります。Class関連で追加されています。options)defineHiddenClassメソッドとの違いは、第2引数のclassDataです。これがクラスデータと呼ばれるものです。dataとなっています。定数も1つ追加されました。ORIGINALこれはlookupModeで使用する定数ですが、他のMODULEとかPRIVATEなどの定数との違いはよく分かりません。VarHandleクラスVarHandleクラスは、MethodHandleクラスの変数版です。このVarHandleクラスをinvokeできるかどうかに関するメソッドが3つ追加されました。withInvokeExactBehavior()VarHandleオブジェクトに対してinvokeを行うのはMethodHandleクラスですが、型を厳密に一致させる必要があるのがinvokeExactメソッド、必要に応じて引数や戻り値の変換もできるのがinvokeメソッドです。invokeExact/invokeメソッドの引数に指定するのがVarHandleクラスですが、invokeExactメソッドを使用する時には厳密性があるかどうかがチェックされます。このチェックにhasInvokeExactBehaiviorメソッドが使われます。withInvokeBehaiviorメソッドとwithInvokeExactBehaiviorメソッドでinvocation時の振る舞いを変更することができます。APIのフォーマッタに関するパッケージです。DateTimeFormatterBuilderクラスDateTimeFormatterBuilderクラスはDateTimeFormatterオブジェクトを生成するためのビルダークラスです。Periodを表す文字列を追加するメソッドが追加されました。style)実際に試してみましょう。System.out.println(formatter.format(time))昼というように15時だと、"昼"とフォーマットされました。ところが、FULLでもNARROWでもSHORTのどれでも"昼"になってしまうんですよね。afternoonになってしまいます。APIが変更されたのだから、java.utilパッケージのコレクションに関連したのが追加されたのかと思ったのですが、空振りでしたwObjectsクラスObjectsクラスには範囲のチェックを行うcheckIndexメソッドやcheckFromIndexSizeメソッドがあるのですが、これに関連して3種類のオーバーロードが追加されました。length)違いは引数の型がintではなく、longになったということです。IndexOutOfBoundsException例外に関連しているんでしょうね。java.compiler/javax.lang.modelパッケージ毎度毎度のjavax.lang.modelパッケージです。15に対応する定数が追加されました。RELEASE_16java.desktop/javax.swingパッケージSwingにAPIの変更があるなんてビックリです。JPasswordFieldクラスパスワード用のテキストフィールドを表すJPasswordFieldクラスですが、スーパークラスのsetTextメソッドがオーバーライドされています。t)なぜこのタイミングでこの変更が行われたのか、まったく分かりませんwJSlider.AccessibleJSliderクラススライダーを表すJSliderクラス用のアクセシビリティ対応のクラスがAccessibleJSliderクラスですが、ChangeListenerインタフェースを実装しています。Feelに関する部分でオーバーライドがいくつか追加されているのですが、省略します。APIにスレッド関連のAPIが追加されました。LogRecordクラスログの1行に相当するLogRecordクラスにはスレッドのIDを記録できたのですが、これに関連して2つのメソッドが追加されました。longThreadID)これまで、スレッドのIDはintだったのですが、OSによってはlongのものがあるということでlongも扱えるようになったということのようです。Clientがjava.net.httpモジュールのjava.net.httpパッケージで定義されています。HttpRequestクラスHttpRequestオブジェクトを生成するためのビルダークラスがHttpRequest.Builderクラスです。このBuilderクラスのファクトリメソッドが1つ追加されました。filter)すでに存在するHttpRequestオブジェクトを再利用して、新しいHttpRequestオブジェクトを生成するためのビルダーのファクトリメソッドです。第1引数が既存のHttpRequestオブジェクト、第2引数が第1引数のHttpRequestオブジェクトのヘッダーを残すかどうかを決めるフィルタになります。BiPredicateインタフェースなので引数が2つ、戻り値の型がbooleanですが、第1引数がヘッダ名、第2引数にその値が指定されます。残すのであればture、残さないのであればflaseを返します。HttpRequest.BodyPublishersクラスPOSTでHttpRequestオブジェクトを生成する時のボディを作成するのがBodyPublishersクラスです。BodyPublishersクラスはstaticメソッドのファクトリメソッドだけが定義されているのですが、そのファクトリメソッドが1つ追加されました。publishers)複数のBodyPublishersオブジェクトを連結させて、複数のボディを生成するBodyPublishersオブジェクトを生成するファクトリメソッドです。いうことで、一通りAPIの変更をさらってきましたが、LTSの1つ前のバージョンというのが如実に表れているような気がします。JEPで策定した以外の変更も多かったですね。17は変更が少ないのかもしれません。少なくともIncubatorやPreviewは入れにくいでしょうし。17に移行するのも楽かもしれませんね。