NumberFormatException
次のコードを実行するとどうなるでしょうか?
"80000000".toInt(radix = 16)
NumberFormatException
が throw
されます
Exception in thread "main" java.lang.NumberFormatException: For input string: "80000000" under radix 16
at java.lang.NumberFormatException.forInputString (:-1)
at java.lang.Integer.parseInt (:-1)
at FileKt.main (File.kt:7)
理由は Int.MAX_VALUE
が 2147483647 で 16進数表記で 7FFFFFFF(16) なので、 8000000(16) は Int.MAX_VALUE
を超えてしまうからです。
ちなみにこれと同じような表現を Dart と Swift で書くとどうなるでしょうか?
Dart
int.parse('80000000', radix: 16);
Swift
Int("80000000", radix: 16)
いずれも 2147483648 に変換されます。
どちらも 64bit なので Int の最大値は 9,223,372,036,854,775,807 になります。
16進数表記で 7FFFFFFFFFFFFFFF(16) なので、 8000000000000000(16) で最大値を超えます。
Swift は Int の最大値を超えると nil
を返します。
一方、 Dart は 9223372036854776000 という中途半端な数値を返します。
DartPad で試しているので、この制限かもしれません。
If the source string does not contain a valid integer literal, optionally prefixed by a sign, a FormatException is thrown.
FormatException
が throw
されそうですが、確認できていないです。
さて、戻って Kotlin では toInt
の内部では Java の Integer.parseInt
が呼ばれて、 NumberFormatException
を throw
しています。
回避としては、
toIntOrNull
toLong
toIntOrNull
Int.MAX_VALUE
が 2147483647 を超えたら null
を返すようにします。 null かどうかを Kotlin で扱うのは次のように安全に扱えます。
"80000000".toIntOrNull(radix = 16)?.let { /* process */ }
toLong
Long.MAX_VALUE
9,223,372,036,854,775,807 まで扱えるようになりますが、これを超えると NumberFormatException
を避けられません。
toIntOrNull
と toLong
を組み合わせて、 toLongOrNull
を利用すると Swift と同じように扱えるようになります。
"8000000000000000".toLongOrNull(radix = 16)?.let { /* process */ }
if let it = Int("8000000000000000", radix: 16) { /* process */ }
Swift Int は正確にはプラットフォームに依存するため、 32-bit 環境なら同様の問題に直面してました
On 32-bit platforms, Int is the same size as Int32, and on 64-bit platforms, Int is the same size as Int64.