JDK 17: Hexadecimal Formatting and Parsing

このエントリは以下の文章をベースにしています(原文に対して変更している箇所があります)。
原文はこちら。
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個の静的ファクトリメソッド HexFormatHexFormat.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が使われています。以下はその例です。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中