Open1

java.lang.NumberFormatException: Error at index x in: "string"

ふじしろふじしろ

概要

UUID.fromStringメソッド使用時に発生したエラーへの対応

java.lang.NumberFormatException: Error at index 3 in: "340v8400" # "340v8400"はUUIDの最初の区切りの文字列
	at java.base/java.lang.NumberFormatException.forCharSequence(NumberFormatException.java:81)
	at java.base/java.lang.Long.parseLong(Long.java:775)
	at java.base/java.util.UUID.fromString(UUID.java:218)
	at ...(以下略)

結論

元のUUIDを下記で生成したUUIDに差し替えたら動作した。
https://www.uuidgenerator.net/

元のUUIDは一つの自動生成したUUIDに対して、アルファベットを適当にいじったりして組み替えたものだったので、それがUUIDのフォーマットから外れてしまったのかもしれない?

エラーの理解

https://docs.oracle.com/javase/8/docs/api/java/lang/NumberFormatException.html
-> 渡された文字列を数値に変換したいけど、その文字列は数値に変換できないよ

詳細の理解

at java.base/java.util.UUID.fromString(UUID.java:218)

UUID.fromStringメソッドは文字列からUUIDを生成するメソッド。
https://docs.oracle.com/javase/jp/8/docs/api/java/util/UUID.html

218行目は以下の通り

long mostSigBits = Long.parseLong(name, 0, dash1, 16) & 0xffffffffL;

mostSigBits変数に、
文字列変数nameの、
1文字目から最初の"-"が出てくる手前の文字までを、
16進数のLong型に変換する(redix=基数)

かつ、それが 0xffffffffL(16 進形式で表される長整数リテラル。末尾の「L」は、Long型の整数であることを示す)であればOK?

エラーは、このLong.parseLongメソッドで発生している。

at java.base/java.lang.Long.parseLong(Long.java:775)

Long.parseLongは渡された引数の指定の領域を、指定の基数の数値として解析する
https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/lang/Long.html#parseLong(java.lang.CharSequence,int,int,int)

775行目近辺のコードは以下の通り

// Accumulating negatively avoids surprises near MAX_VALUE
int digit = Character.digit(s.charAt(i), radix);
if (digit < 0 || result < multmin) {
    throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i);
}

渡された引数sのi文字目を、指定の基数の数値に変換する
ただし、その数値が負の値またはresult < miltmin(多分今回は関係ない?)である場合はNumberFormatExceptionを投げる。