このエントリは以下の文章をベースにしています(原文に対して変更している箇所があります)。
原文はこちら。
The original article was written by Dustin Marx.
https://marxsoftware.blogspot.com/2020/12/jdk17-hex-formatting-parsing.html
JDK 17早期アクセスビルドのBuild 3で、JDK-8251989の実装が追加されました。16進数値をパース、整形するこの新機能は、新たなクラス java.util.HexFormat
にカプセル化します。
JDK 17 Early-Access Builds
https://jdk.java.net/17/
[JDK-8251989] Hex formatting and parsing utility
https://bugs.openjdk.java.net/browse/JDK-8251989
java.util.HexFormat
クラスに対してjavapを実行すると、簡単にAPIの概要が確認できます。
# javap java.util.HexFormat
Compiled from "HexFormat.java"
public final class java.util.HexFormat {
static final boolean $assertionsDisabled;
public static java.util.HexFormat of();
public static java.util.HexFormat ofDelimiter(java.lang.String);
public java.util.HexFormat withDelimiter(java.lang.String);
public java.util.HexFormat withPrefix(java.lang.String);
public java.util.HexFormat withSuffix(java.lang.String);
public java.util.HexFormat withUpperCase();
public java.util.HexFormat withLowerCase();
public java.lang.String delimiter();
public java.lang.String prefix();
public java.lang.String suffix();
public boolean isUpperCase();
public java.lang.String formatHex(byte[]);
public java.lang.String formatHex(byte[], int, int);
public <A extends java.lang.Appendable> A formatHex(A, byte[]);
public <A extends java.lang.Appendable> A formatHex(A, byte[], int, int);
public byte[] parseHex(java.lang.CharSequence);
public byte[] parseHex(java.lang.CharSequence, int, int);
public byte[] parseHex(char[], int, int);
public char toLowHexDigit(int);
public char toHighHexDigit(int);
public <A extends java.lang.Appendable> A toHexDigits(A, byte);
public java.lang.String toHexDigits(byte);
public java.lang.String toHexDigits(char);
public java.lang.String toHexDigits(short);
public java.lang.String toHexDigits(int);
public java.lang.String toHexDigits(long);
public java.lang.String toHexDigits(long, int);
public boolean isHexDigit(int);
public int fromHexDigit(int);
public int fromHexDigits(java.lang.CharSequence);
public int fromHexDigits(java.lang.CharSequence, int, int);
public long fromHexDigitsToLong(java.lang.CharSequence);
public long fromHexDigitsToLong(java.lang.CharSequence, int, int);
public boolean equals(java.lang.Object);
public int hashCode();
public java.lang.String toString();
static {};
}
javapで生成されたものから、インスタンスを取得するための2個の静的ファクトリメソッド HexFormat
: HexFormat.of()
と HexFormat.ofDelimiter(String)
がわかります。両者とも”preset parameters” を伴うHexFormatのインスタンスを指定します。残りのパブリック・メソッドはインスタンス・メソッドで、通常は5つのカテゴリーのいずれかの動作に使用されます。
HexFormat
インスタンスに、インスタンス生成時にプリセットパラメータとは異なるパラメータを指定するHexFormat
インスタンスの構成済みパラメータを指示する- 16進数表現から/への変換
- 文字や文字列の特徴を示す
- オーバーライドされたObjectメソッド(
toString()
、equals(Object)
、hashCode()
)
HexFormat
のクラスレベルのJavadocでは、HexFormat
クラスの目的が1文でまとめられています。
HexFormat
converts between bytes and chars and hex-encoded strings which may include additional formatting markup such as prefixes, suffixes, and delimiters.(HexFormat
は、バイトと文字列、および接頭辞、接尾辞、区切り文字などの追加のフォーマット・マークアップを含むことができる16進コード化された文字列の間で変換します)
このクラスレベルのJavadocベースのドキュメントには、HexFormat
クラスを適用してこれらのタイプ間を変換したり、接頭辞、接尾辞、デリミタを適用したりする有用な例が記載されています。また、このクラスレベルのドキュメントには、HexFormat
クラスはImmutableでスレッドセーフであり、値ベース・クラス(Value-based classes)であると説明されています。
値ベース・クラス
https://docs.oracle.com/javase/jp/15/docs/api/java.base/java/lang/doc-files/ValueBased.html
Value-based Classes
https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/doc-files/ValueBased.html
HexFormat
クラスのソースコード、早期アクセスAPIドキュメントは以下にあります。
HexFormat.java(Masterブランチ)
https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/HexFormat.java
Class HexFormat
https://download.java.net/java/early_access/jdk17/docs/api/java.base/java/util/HexFormat.html
この記事では、HexFormat
を使った例をいくつか取り上げます。これらはGitHubで公開しています。
HexadecimalDemonstration.java
https://github.com/dustinmarx/javademos/blob/master/src/dustin/examples/jdk17/hex/HexadecimalDemonstration.java
幸いなことに、クラスレベルのJavadocベースのAPIドキュメントで、HexFormat
のよい利用例が例示されています。上記デモコードでは、このクラスの基本的な利用方法をご紹介しています。
Acquiring an Instance of HexFormat
HexFormatインスタンスの取得用に2個の静的メソッドがありますが、そのうちの1個のデモコードです。
/** Instance of {@link HexFormat} used in this demonstration. */
private static final HexFormat HEX_FORMAT_UPPER_CASE = HexFormat.of().withUpperCase();
withUpperCase()
メソッドはHexFormat
のインスタンスに対し、大文字の16進文字(0~9、A~F)を使うように指示します。
Converting Integers to Hexadecimal
以下は、 HexFormat.toHexDigits()
のデモコードです。
/**
* Demonstrates use of {@link HexFormat#toHexDigits(int)}.
*/
public void demoIntegerToHexadecimal()
{
for (int integerValue = 0; integerValue < 17; integerValue++)
{
out.println("Hexadecimal representation of integer " + integerValue + ": '"
+ HEX_FORMAT_UPPER_CASE.toHexDigits(integerValue) + "'.");
}
}
上記コードスニペットの実行結果は以下のようになります。
Hexadecimal representation of integer 0: '00000000'.
Hexadecimal representation of integer 1: '00000001'.
Hexadecimal representation of integer 2: '00000002'.
Hexadecimal representation of integer 3: '00000003'.
Hexadecimal representation of integer 4: '00000004'.
Hexadecimal representation of integer 5: '00000005'.
Hexadecimal representation of integer 6: '00000006'.
Hexadecimal representation of integer 7: '00000007'.
Hexadecimal representation of integer 8: '00000008'.
Hexadecimal representation of integer 9: '00000009'.
Hexadecimal representation of integer 10: '0000000A'.
Hexadecimal representation of integer 11: '0000000B'.
Hexadecimal representation of integer 12: '0000000C'.
Hexadecimal representation of integer 13: '0000000D'.
Hexadecimal representation of integer 14: '0000000E'.
Hexadecimal representation of integer 15: '0000000F'.
Hexadecimal representation of integer 16: '00000010'.
Demonstrating HexFormat.isHexDigit(int)
以下は HexFormat.isHexDigit(int)
のデモコードです。
/**
* Demonstrates use of {@link HexFormat#isHexDigit(int)}.
*/
public void demoIsHex()
{
for (char characterValue = 'a'; characterValue < 'i'; characterValue++)
{
out.println("Is character '" + characterValue + "' a hexadecimal value? "
+ HEX_FORMAT_UPPER_CASE.isHexDigit(characterValue));
}
for (char characterValue = 'A'; characterValue < 'I'; characterValue++)
{
out.println("Is character '" + characterValue + "' a hexadecimal value? "
+ HEX_FORMAT_UPPER_CASE.isHexDigit(characterValue));
}
}
上記コードスニペットの実行結果は以下の通りです。
Is character 'a' a hexadecimal value? true
Is character 'b' a hexadecimal value? true
Is character 'c' a hexadecimal value? true
Is character 'd' a hexadecimal value? true
Is character 'e' a hexadecimal value? true
Is character 'f' a hexadecimal value? true
Is character 'g' a hexadecimal value? false
Is character 'h' a hexadecimal value? false
Is character 'A' a hexadecimal value? true
Is character 'B' a hexadecimal value? true
Is character 'C' a hexadecimal value? true
Is character 'D' a hexadecimal value? true
Is character 'E' a hexadecimal value? true
Is character 'F' a hexadecimal value? true
Is character 'G' a hexadecimal value? false
Is character 'H' a hexadecimal value? false
Demonstrating HexFormat.toString()
HexFormat
クラスでは、Object.toString()
メソッドのオーバーライドされたものを提供しています。以下はデモコードです。
/**
* Demonstrates string representation of instance of
* {@link HexFormat}.
*
* The {@link HexFormat#toString()} method provides a string
* that shows the instance's parameters (not class name):
* "uppercase", "delimiter", "prefix", and "suffix"
*/
public void demoToString()
{
out.println("HexFormat.toString(): " + HEX_FORMAT_UPPER_CASE);
}
上記コードスニペット実行結果は以下の通りです。
HexFormat.toString(): uppercase: true, delimiter: "", prefix: "", suffix: ""
Other Examples of HexFormat
HexFormat
のJavadocベースのクラスレベルドキュメントには、このクラスのより多くの利用例があります。この例は、HexFormat.of()
と HexFormat.ofDelimiter(String)
というインストールメソッド、 toHexDigit(byte)
、fromHexDigits(CharSequence)
、formatHex(byte[])
、parseHex(String)
というユーティリティメソッド、withUpperCase()
とwithPrefix(String)
という特殊化メソッドを説明するものです。後者の例は実用的な場面(バイト・フィンガープリントなど)での操作を想定した現実的な例である点がGoodです。
Public key fingerprint
https://en.wikipedia.org/wiki/Public_key_fingerprint
指紋 (公開鍵暗号)
https://ja.wikipedia.org/wiki/指紋_(公開鍵暗号)
JDK Uses of HexFormat
JDKおよびそのテストでは既にHexFormatが使われています。以下はその例です。
- 8252055: Use java.util.HexFormat in java.security
https://github.com/openjdk/jdk/pull/1828 - 8258796: [test] Apply HexFormat to tests for java.security
https://github.com/openjdk/jdk/pull/2006 - 8259493: [test] Use HexFormat instead of adhoc hex utilities in network code and locale SoftKeys
https://github.com/openjdk/jdk/pull/2009