Java Tips | 基本ユーティリティ:型変換

Java Java
スポンサーリンク

型変換は「データを正しい器に入れ直す」作業

業務システムでは、同じ「値」でも、場面によって求められる型が変わります。
画面からは文字列で届く、計算には数値が必要、DB には文字列で保存する──この「型の行き来」をきちんと設計するのが型変換です。

Java では、プリミティブ型(intdouble)とラッパークラス(IntegerDouble)、String との間を行き来することが非常に多くなります。
ここを雑にやると、NumberFormatExceptionNullPointerException、桁落ち・丸め誤差など、業務バグの温床になります。


まずは「文字列 ↔ 数値」の基本型変換を押さえる

String → int / long の変換

文字列から整数への変換は、業務で一番よく出てきます。代表的なのは Integer.parseIntInteger.valueOf です。

String s = "123";

// プリミティブ int に変換
int i = Integer.parseInt(s);

// ラッパー型 Integer に変換
Integer iObj = Integer.valueOf(s);
Java

parseInt はプリミティブ int を返し、valueOfInteger オブジェクトを返します。
オブジェクトが欲しい場面(コレクションに入れる、null を扱いたいなど)では valueOf
単純な計算でパフォーマンス重視なら parseInt、という使い分けが基本です。

ここで重要なのは、「数値として正しい文字列でないと NumberFormatException が出る」ことです。

Integer.parseInt("123");   // OK
Integer.parseInt("123a");  // NumberFormatException
Integer.parseInt("");      // NumberFormatException
Integer.parseInt(null);    // NullPointerException
Java

この「失敗し得る」という感覚を持っておくのが、型変換を安全に扱う第一歩です。

int / long → String の変換

逆に、数値を文字列にしたい場面も多いです。代表的な方法は String.valueOftoString です。

int i = 123;

// String に変換
String s1 = String.valueOf(i);
String s2 = Integer.toString(i);
Java

String.valueOfnull にも優しく、ラッパー型にもそのまま使えるので、実務ではかなり出番が多いです。

Integer iObj = null;

String s = String.valueOf(iObj);  // "null" という文字列になる
Java

null をどう扱うか」は要件次第なので、null のときは空文字にしたい、などのポリシーがあるなら、ユーティリティでラップしてしまうのがよくあるパターンです。


プリミティブ型とラッパークラスの変換と注意点

オートボクシング / アンボクシングのイメージ

Java では、プリミティブ型とラッパークラスの間は自動変換(オートボクシング/アンボクシング)が行われます。

int i = 10;
Integer obj = i;   // オートボクシング(int → Integer)
int j = obj;       // アンボクシング(Integer → int)
Java

一見便利ですが、ここに null が絡むと危険です。

Integer obj = null;
int i = obj;  // ここで NullPointerException
Java

業務コードでは、「ラッパー型は null になり得る」という前提を常に意識し、
アンボクシングが起きる場所(int に代入、+ 演算など)では特に注意が必要です。

ラッパー型を返すか、プリミティブを返すか

ユーティリティの設計では、「戻り値をプリミティブにするか、ラッパーにするか」がよく議論になります。

  • プリミティブを返す: null という状態を表現できない代わりに、NPE の心配がない。
  • ラッパーを返す: 「値なし」を null で表現できるが、アンボクシング時の NPE に注意が必要。

例えば「パースできなかったら null を返したい」ならラッパー型、
「常に何かしらの値(デフォルト値を含む)を返したい」ならプリミティブ型、という設計になります。


実務で使う「安全な型変換ユーティリティ」の例

文字列 → 整数の安全な変換

生の parseInt をあちこちで呼ぶのではなく、「失敗したらどうするか」を含めてユーティリティ化しておくと、業務コードが安定します。

public final class Conversions {

    private Conversions() {}

    // null / 空白 / 不正な形式 → null、それ以外は Integer
    public static Integer toIntegerOrNull(String s) {
        if (s == null || s.isBlank()) {
            return null;
        }
        try {
            return Integer.valueOf(s.trim());
        } catch (NumberFormatException e) {
            return null;
        }
    }

    // パースできなければデフォルト値を返す
    public static int toIntOrDefault(String s, int defaultValue) {
        Integer value = toIntegerOrNull(s);
        return value != null ? value : defaultValue;
    }
}
Java

使う側はこうなります。

String input = getAgeInput();  // 画面からの入力

int age = Conversions.toIntOrDefault(input, 0);

if (age <= 0) {
    System.out.println("年齢を正しく入力してください");
}
Java

ここで大事なのは、「例外を業務ロジックにばらまかず、ユーティリティで吸収している」ことです。
これにより、画面やバッチのコードは「変換に失敗したら 0 が返る」という前提でシンプルに書けます。

文字列 → 真偽値の変換

真偽値も、画面や設定ファイルから文字列で届くことが多いです。

public static Boolean toBooleanOrNull(String s) {
    if (s == null) return null;
    return switch (s.trim().toLowerCase()) {
        case "true", "1", "yes", "y", "on" -> Boolean.TRUE;
        case "false", "0", "no", "n", "off" -> Boolean.FALSE;
        default -> null;
    };
}
Java

Java 標準の Boolean.parseBoolean は、「"true"(大文字小文字無視)なら true、それ以外は false」という挙動なので、
「不正な値を false とみなしてよいか?」という観点で要件に合わないこともあります。
業務では、「不正な値はエラー扱いにしたい」「null にしたい」といった要件に合わせて、自前の変換ルールを持つことが多いです。


数値型どうしの変換と精度の話

int / long / double 間のキャスト

数値型どうしの変換は、キャストで行います。

int i = 10;
long l = i;        // 拡大変換(安全)

long big = 10000000000L;
int small = (int) big;  // 縮小変換(桁落ちの可能性)
Java

int → long のような「入れ物が大きくなる」変換は安全ですが、
long → int のような「入れ物が小さくなる」変換は、値が範囲外だと桁落ちします。

long big = 3_000_000_000L;
int small = (int) big;

System.out.println(small);  // 予想外の負の値になる
Java

業務で金額や数量を扱うときは、「どの型まで許容するか」「範囲外をどう扱うか」を決めたうえでキャストする必要があります。

金額・精度が重要な値は BigDecimal で扱う

doublefloat は二進数の浮動小数点数なので、10 進数の小数を正確に表現できないことがあります。
金額や精度が重要な値には BigDecimal を使うのが定番です。

import java.math.BigDecimal;

BigDecimal price = new BigDecimal("1234.56");  // 文字列からの生成が推奨

BigDecimal taxRate = new BigDecimal("0.1");
BigDecimal tax = price.multiply(taxRate);
Java

new BigDecimal(double) は、double の誤差をそのまま持ち込んでしまうので、
「文字列 → BigDecimal」の変換では new BigDecimal(String) を使うのがベストプラクティスです。


String 以外の型変換と設計の考え方

Enum との相互変換

業務では、「コード値(文字列) ↔ Enum」の変換もよく出てきます。

enum Status {
    ACTIVE, INACTIVE;
}

Status st = Status.valueOf("ACTIVE");  // 文字列 → Enum
String name = st.name();               // Enum → 文字列
Java

valueOf は不正な文字列を渡すと IllegalArgumentException になるので、
ここでも「失敗したらどうするか」を含めてユーティリティ化しておくと安全です。

public static Status toStatusOrNull(String s) {
    if (s == null) return null;
    try {
        return Status.valueOf(s.toUpperCase());
    } catch (IllegalArgumentException e) {
        return null;
    }
}
Java

「どこで型を決めるか」を意識する

型変換の設計で一番大事なのは、「どこで最初に正しい型に変換するか」です。

  • 画面や外部 API からは、まず文字列で受ける。
  • できるだけ早い段階で、業務で使う型(intBigDecimalEnum など)に変換する。
  • 以降のレイヤーでは、その型を前提にロジックを書く。

この「早めに正しい器に入れ直す」発想があると、
後ろのレイヤーで「毎回 String からパースする」「毎回 null チェックする」といった重複が減り、バグも減ります。


まとめ:初心者が型変換で身につけるべき感覚

型変換で外したくないポイント

  • String ↔ 数値の基本を押さえる
    parseInt / valueOf / String.valueOf の役割と違いを理解し、NumberFormatException がいつ出るかを体感しておく。
  • プリミティブとラッパーの違いを意識する
    null を扱う必要があるかどうかで、どちらを使うか決める。アンボクシング時の NPE に注意する。
  • 「失敗し得る変換」はユーティリティで包む
    文字列 → 数値、文字列 → Enum、文字列 → 真偽値などは、try-catch とポリシー(デフォルト値・null・例外)をセットでユーティリティ化する。
  • 精度が大事なところでは BigDecimal を使う
    金額や割合など、誤差が許されない値は double ではなく BigDecimal + 文字列変換で扱う。

ここまでの感覚が身につけば、「とりあえずキャスト」「とりあえず parseInt」から卒業できます。

タイトルとURLをコピーしました