数値パースは「文字列をちゃんとした数字にする」作業
業務システムでは、画面入力や CSV、外部 API から「文字列として届いた数字」を、本物の int や long、BigDecimal に変換する場面が山ほど出てきます。
この「文字列 → 数値」への変換を、一般に「数値パース(number parsing)」と呼びます。
Java では、Integer.parseInt や Double.parseDouble などのメソッドで数値パースを行いますが、形式が不正な文字列を渡すと NumberFormatException という例外が発生します。
業務コードではこの例外が頻出で、「ちゃんとパースできるか」「失敗したときどう扱うか」を設計しておくことがとても重要になります
基本の parseInt / parseLong / parseDouble を押さえる
代表的なパースメソッドとその挙動
Java 標準の代表的な数値パースメソッドは次の通りです。
Integer.parseInt(String s): 文字列をintに変換する。Long.parseLong(String s): 文字列をlongに変換する。Double.parseDouble(String s)/Float.parseFloat(String s): 文字列を浮動小数点数に変換する。
使い方はとてもシンプルです。
int i = Integer.parseInt("123");
long l = Long.parseLong("456");
double d = Double.parseDouble("3.14");
System.out.println(i); // 123
System.out.println(l); // 456
System.out.println(d); // 3.14
Javaここで重要なのは、「完全に数字として正しい形式の文字列しか受け付けない」という点です。
数字以外の文字が混ざっていたり、空文字だったり、範囲外の値だったりすると、NumberFormatException がスローされます。
NumberFormatException が出る典型パターンを体感する
いくつか「わざと失敗させる」例を見てみましょう。
Integer.parseInt("abc"); // 文字が混じっている → 例外
Integer.parseInt(""); // 空文字 → 例外
Integer.parseInt("12a3"); // 一部だけ数字 → 例外
Integer.parseInt("123"); // 全角数字を含む → 例外
Integer.parseInt("1,000"); // カンマ付き → 例外
Integer.parseInt(" 123 "); // 前後に空白 → 例外
Integer.parseInt("999999999999"); // int の範囲外 → 例外
Javaこれらはすべて NumberFormatException の原因としてよく挙げられるパターンです。
見た目は「数字っぽい」のに Java からすると「これは数字じゃない」と判断される、というギャップがバグの元になります。
例外を前提にした「素のパース」と try-catch
例外をそのまま上に投げるスタイル
もっとも素朴な書き方は、例外を特に捕まえず、そのまま上位に投げるスタイルです。
public int parseAge(String input) {
return Integer.parseInt(input); // 不正なら NumberFormatException がそのまま飛ぶ
}
Javaこの場合、呼び出し側は「ここで例外が飛ぶかもしれない」と意識しておく必要があります。
業務ロジックの中で「ここは絶対に数字が来るはず」という前提が固いなら、このスタイルでも構いません。
try-catch でパース失敗を受け止める
ユーザー入力や外部データのように「不正な値が普通に来る」場面では、try-catch で NumberFormatException を受け止めるのが基本です。
public Integer parseAgeOrNull(String input) {
try {
return Integer.parseInt(input);
} catch (NumberFormatException e) {
return null; // パースできなければ null を返す
}
}
Java呼び出し側はこうなります。
String input = getAgeInput(); // 画面からの入力
Integer age = parseAgeOrNull(input);
if (age == null) {
System.out.println("年齢は数字で入力してください");
} else {
System.out.println("年齢は " + age + " 歳です");
}
Javaここでのポイントは、「例外を業務ロジックに直接ばらまかず、ユーティリティで吸収する」という設計です。
これにより、画面やバッチのコードが「パース失敗時の扱い」を意識しやすくなります。
実務でよく使う「安全な数値パースユーティリティ」
null や空文字、空白をまとめて扱う
現場では、「null や空文字、空白だけの文字列は『値なし』として扱いたい」という要件が多いです。
そのたびに if (s == null || s.isBlank()) と書くのは面倒なので、ユーティリティにまとめてしまいます。
public final class Numbers {
private Numbers() {}
// null / 空文字 / 空白だけ → null、それ以外は int にパース
public static Integer parseIntOrNull(String s) {
if (s == null || s.isBlank()) {
return null;
}
try {
return Integer.parseInt(s.trim());
} catch (NumberFormatException e) {
return null;
}
}
// パースできなければデフォルト値を返す版
public static int parseIntOrDefault(String s, int defaultValue) {
Integer value = parseIntOrNull(s);
return value != null ? value : defaultValue;
}
}
Java使い方はこうです。
String input = getAgeInput(); // " 20 " や "" や "abc" かもしれない
int age = Numbers.parseIntOrDefault(input, 0);
if (age <= 0) {
System.out.println("年齢を正しく入力してください");
} else {
System.out.println("年齢は " + age + " 歳です");
}
Javaここで重要なのは、次のような「現実世界の汚れた入力」を一箇所で吸収していることです。
- 前後に空白が付いている
" 20 " - 空文字や空白だけ
""," " - 数字以外が混ざっている
"20歳"
こうした「よくある汚れ」をユーティリティで処理しておくと、業務ロジック側は「きれいな int が来る」と信じて書けるようになります。
範囲チェックを組み込んだパース
年齢や数量など、「あり得る範囲」が決まっている数値は、パースと同時に範囲チェックもしてしまうと安全です。
public static Integer parseAge(String s) {
Integer value = parseIntOrNull(s);
if (value == null) {
return null;
}
if (value < 0 || value > 150) {
return null; // 業務的にあり得ない値は無効扱い
}
return value;
}
Javaこうしておくと、「-1 歳」や「9999 歳」といった値が DB に紛れ込むのを防げます。
パースとバリデーションをセットで考えるのが、実務的な設計のコツです。
カンマ付き・全角数字・小数などの「現場あるある」への対応
カンマ付き数値 “1,000” を扱う
業務では、画面や Excel から「1,000」のようなカンマ付き数値が来ることがよくあります。Integer.parseInt("1,000") はそのままだと NumberFormatException になります。
シンプルな対処としては、「カンマを事前に取り除く」方法があります。
public static Integer parseIntWithComma(String s) {
if (s == null || s.isBlank()) {
return null;
}
String normalized = s.replace(",", "").trim();
try {
return Integer.parseInt(normalized);
} catch (NumberFormatException e) {
return null;
}
}
Javaこれで "1,000" も " 2,500 " も "1000" も同じように扱えます。
ただし、「小数点やマイナス記号も許可するか」「桁区切りの位置が正しいか」など、要件に応じてルールを決める必要があります。
全角数字や全角マイナスの扱い
日本語環境では、「123」のような全角数字が紛れ込むこともあります。
Java から見ると全角数字は別の文字なので、そのままではパースできません。
簡易的な対処としては、「全角数字を半角に変換してからパースする」方法があります。
これは自前でマッピングしてもいいですし、外部ライブラリを使うこともあります。
public static String toHalfWidthDigits(String s) {
if (s == null) return null;
StringBuilder sb = new StringBuilder(s.length());
for (char c : s.toCharArray()) {
if (c >= '0' && c <= '9') {
sb.append((char) (c - '0' + '0'));
} else {
sb.append(c);
}
}
return sb.toString();
}
Javaこれをパース前に挟めば、"123" も "123" として扱えるようになります。
ただし、「全角を許可するかどうか」は業務要件次第なので、チームで方針を決めておくことが大事です。
小数・金額・精度の話
Double.parseDouble で小数をパースすることもできますが、金額や精度が重要な値には BigDecimal を使うのが一般的です。BigDecimal には new BigDecimal(String) コンストラクタがあり、これも不正な形式の文字列を渡すと NumberFormatException をスローします。
BigDecimal price = new BigDecimal("1234.56"); // OK
BigDecimal bad = new BigDecimal("1,234.56"); // 例外
Java金額を扱うときは、「カンマをどうするか」「小数点以下の桁数をどう制限するか」などを含めて、専用のパースユーティリティを用意しておくと安全です。
まとめ:初心者が身につけるべき数値パースの感覚
数値パースでまず押さえるべきこと
- 「文字列 → 数値」は常に失敗し得る
見た目が数字でも、空白・カンマ・全角・範囲外などで簡単にNumberFormatExceptionが出ることを体感しておく。 - 例外をそのまま放置しない
ユーティリティでtry-catchし、nullやデフォルト値、エラーコードなどに変換して、業務ロジックが扱いやすい形にする。 - 「パース」と「バリデーション」をセットで考える
年齢なら範囲チェック、金額なら桁数や符号のチェックなど、「業務的にあり得る値か」を同時に確認する。
ここまでの感覚が身につけば、数値パースで振り回されることはかなり減ります。
