JEP 外の JDK 21 における変更点を、開発時に覚えておきたいものに絞りまとめておきます。
- Math.clamp() メソッドの追加
- 範囲指定可能な String.indexOf()
- 区切り文字を含めて分割する String.splitWithDelimiters()
- StringBuilder.repeat
- Unicode 絵文字プロパティ
- HttpClient のクローズ処理
- JFR.View コマンド
Math.clamp() メソッドの追加
最小値と最大値で切り詰める場合は以下のようにしていました。
Math.min(max, Math.max(value, min));
以下が可能になりました。
Math.clamp(value, min, max);
int
long
float
double
のオーバーロードがあります。
StrictMath.clamp()
にも同様のメソッドが追加されていますが、これは単に Math.clamp()
に委譲しているだけです。
範囲指定可能な String.indexOf()
String
クラスに以下のメソッドが追加されました。
public int indexOf(int ch, int beginIndex, int endIndex) { ... } public int indexOf(String str, int beginIndex, int endIndex) { ... }
旧来は、fromIndex
が指定できる indexOf()
のみであり、検索範囲の終端を指定することができませんできた。
endIndex
を指定することで長い文字列の部分検索が効率化できます。endIndex
は慣例に則り、excluded となっており、endIndex
の要素は含まれません。
区切り文字を含めて分割する String.splitWithDelimiters()
split()
は結果に区切り文字を含みません。
var string = "aa:bb::cc"; string.split(":"); // -> [aa, bb, , cc]
区切り文字を含めるには、ゼロ幅マッチの正規表現で以下のように頑張る必要があります。
string.split("(?<=:)"); // -> [aa:, bb:, :, cc] string.split("(?=:)"); // -> [aa, :bb, :, :cc] string.split("((?<=:)|(?=:))"); // -> [aa, :, bb, :, :, cc]
String
クラスに splitWithDelimiters()
が追加され、上記3つ目のケースがカバーされます。
public String[] splitWithDelimiters(String regex, int limit) { ... }
以下のようになります。
string.splitWithDelimiters(":", -1); // -> [aa, :, bb, :, , :, cc]
Pattern
にも同様のメソッドが追加されています。
Pattern.compile(regex).splitWithDelimiters(str, n)
ゼロ幅マッチの正規表現については以下を参照してください。
StringBuilder.repeat
Java11 で String.repeat(int count)
が追加されたのと同様に、StringBuilder
と StringBuffer
にも repeat()
が追加されました。
public StringBuilder repeat(int codePoint, int count) { ... } public StringBuilder repeat(CharSequence cs, int count) { ... }
public synchronized StringBuffer repeat(int codePoint, int count) { ... } public synchronized StringBuffer repeat(CharSequence cs, int count) { ... }
以下のように利用できます。
var sb = new StringBuilder(); sb.repeat('*', 10);
Unicode 絵文字プロパティ
java.lang.Character
に絵文字プロパティを取得するメソッドが追加されました。
Character.isEmoji("😊".codePointAt(0)); // -> true
その他、isEmojiPresentation(int codePoint)
isEmojiModifier(int codePoint)
isEmojiModifierBase(int codePoint)
isEmojiComponent(int codePoint)
isExtendedPictographic(int codePoint)
も同じです。
正規表現のクラスについても利用可能です。
Pattern.compile("\\p{IsEmoji}").matcher("..");
詳細は以下を参照してください。
ただ、0-9#*
のような文字もUnicode上は絵文字のカテゴリになるので注意点が必要です(emoji keycap sequence で、他の文字と組み合わせて絵文字を構成するため)。
Character.isEmoji("*".codePointAt(0)); // -> true
HttpClient のクローズ処理
Java 11 で導入された java.net.http.HttpClient
に以下のクローズ処理がAPIとして追加されました。
void close()
void shutdown()
void shutdownNow()
boolean awaitTermination(Duration duration)
boolean isTerminated()
合わせて AutoCloseable
を実装するようになりました。
public abstract class HttpClient implements AutoCloseable { }
HttpClient
は通常、それ自身で接続プールを管理しているため、インスタンス生成とcloseを繰り返す使い方はせず、アプリケーション実行中は同じインスタンスを使うため、あまり困りませんでしたが、都合により頻繁にインスタンス生成を行う必要がある場合に(どういう状況?) close()
によりリソースの解放を促進できるようになりました。
JFR.View コマンド
JFR(Java Flight Recorder) ツールに view
コマンドが追加されました。
レコードファイルのダンプやイベント データの集計を簡単に表示することができます。
-XX:StartFlightRecording
オプション、または JFR.start
でJFRを有効にし、ビューを指定して、例えば以下のように JDK Mission Control などを起動することなく、イベントデータを確認できます。
$ jcmd <pid> JFR.start $ jcmd <pid> JFR.view gc Garbage Collections Start GC ID Type Heap Before GC Heap After GC Longest Pause -------- ----- ------------------------ -------------- ------------- ------------- 00:00:00 2 Young Garbage Collection 149.3 MB 17.5 MB 5.63 ms 00:00:00 3 Young Garbage Collection 157.5 MB 17.3 MB 4.12 ms 00:00:00 4 Young Garbage Collection 157.3 MB 17.8 MB 4.46 ms 00:00:00 5 Young Garbage Collection 157.8 MB 17.4 MB 4.06 ms ...
JFR.start
のオプションには以下があります。
Options: cell-height (Optional) Maximum number of rows in a table cell. (INTEGER, no default value) maxage (Optional) Length of time for the view to span. (INTEGER followed by 's' for seconds 'm' for minutes or 'h' for hours, default value is 10m) maxsize (Optional) Maximum size for the view to span in bytes if one of the following suffixes is not used: 'm' or 'M' for megabytes OR 'g' or 'G' for gigabytes. (STRING, default value is 32MB) truncate (Optional) How to truncate content that exceeds space in a table cell. Mode can be 'beginning' or 'end'. (STRING, default value 'end') verbose (Optional) Displays the query that makes up the view. (BOOLEAN, default value false) <view> (Mandatory) Name of the view or event type to display. See list below for available views. (STRING, no default value) width (Optional) The width of the view in characters (INTEGER, no default value) Java virtual machine views: class-modifications gc-concurrent-phases longest-compilations compiler-configuration gc-configuration native-memory-committed compiler-phases gc-cpu-time native-memory-reserved compiler-statistics gc-pause-phases safepoints deoptimizations-by-reason gc-pauses tlabs deoptimizations-by-site gc-references vm-operations gc heap-configuration Environment views: active-recordings cpu-information jvm-flags active-settings cpu-load native-libraries container-configuration cpu-load-samples network-utilization container-cpu-throttling cpu-tsc recording container-cpu-usage environment-variables system-information container-io-usage events-by-count system-processes container-memory-usage events-by-name system-properties Application views: allocation-by-class exception-count native-methods allocation-by-site file-reads-by-path object-statistics allocation-by-thread file-writes-by-path pinned-threads class-loaders finalizers socket-reads-by-host contention-by-address hot-methods socket-writes-by-host contention-by-class latencies-by-type thread-allocation contention-by-site longest-class-loading thread-count contention-by-thread memory-leaks-by-class thread-cpu-load exception-by-message memory-leaks-by-site thread-start exception-by-site modules The <view> parameter can be an event type name. Use the 'JFR.view types' to see a list. To display all views, use 'JFR.view all-views'. To display all events, use 'JFR.view all-events'. Example usage: $ jcmd <pid> JFR.view gc $ jcmd <pid> JFR.view width=160 hot-methods $ jcmd <pid> JFR.view verbose=true allocation-by-class $ jcmd <pid> JFR.view contention-by-site $ jcmd <pid> JFR.view jdk.GarbageCollection $ jcmd <pid> JFR.view cell-height=5 ThreadStart $ jcmd <pid> JFR.view truncate=beginning SystemProcess