JavaのString.formatとは、"%05d"のような書式指定子を使って、数値や文字列を決まった形の文字列に整えるメソッドです。 0埋めは%05d、桁区切りは%,d、小数2桁は%.2f、左寄せは%-10sと書きます。Java 15以降は"%05d".formatted(n)とも書けます。

この記事では、書式指定子を「指定子・入力・出力」の3列で並べた早見表(50項目以上)を最初に示します。出力はすべてOpenJDK 21.0.10で実際に動かした結果で、空白が見えるように[ ]で囲んでいます。さらに、printf・formatted・MessageFormat・DecimalFormat・NumberFormatの使い分け、ドイツ語ロケールで小数点がカンマになる例、全角文字で桁がずれる理由と直し方、MissingFormatArgumentExceptionなどの例外を実際のエラー文で再現します。

String.format書式指定子の早見表

よく使う書式を「やりたいこと」順にまとめました。 「出力」列はJava 21.0.10でString.format(Locale.ROOT, 指定子, 入力)を実行した結果です([ ]は空白を見せるための囲みで、出力には含まれません)。

整数(%d・%x・%o)

やりたいこと 指定子 入力 出力
そのまま %d 42 [42]
右寄せ(幅5) %5d 42 [ 42]
左寄せ(幅5) %-5d 42 [42 ]
0埋め(5桁) %05d 42 [00042]
0埋め(負の数) %05d -42 [-0042]
3桁ごとのカンマ %,d 1234567 [1,234,567]
符号を必ず付ける %+d 42 [+42]
正の数の前に空白 % d 42 [ 42]
負の数をかっこで %(d -42 [(42)]
16進数(小文字) %x 255 [ff]
16進数(大文字) %X 255 [FF]
16進数に0xを付ける %#x 255 [0xff]
16進数を8桁0埋め %08X 48879 [0000BEEF]
8進数 %o 8 [10]
負の数の16進数 %x -1 [ffffffff]
longもそのまま %d 12345678901L [12345678901]

小数(%f・%e・%g)

やりたいこと 指定子 入力 出力
そのまま(既定は小数6桁) %f 3.14159 [3.141590]
小数2桁(四捨五入) %.2f 3.14159 [3.14]
整数に丸める %.0f 2.5 [3]
整数に丸める %.0f 3.5 [4]
小数2桁 %.2f 1.005 [1.01]
幅8・小数2桁で右寄せ %8.2f 3.14159 [ 3.14]
幅8・小数2桁で0埋め %08.2f -3.14159 [-0003.14]
桁区切り+小数2桁 %,.2f 1234567.891 [1,234,567.89]
指数表記 %e 12345.678 [1.234568e+04]
指数表記(大文字・2桁) %.2E 12345.678 [1.23E+04]
大きさで自動切り替え %g 0.00012345 [0.000123450]
16進浮動小数点 %a 1.0 [0x1.0p0]
パーセント表示 %.1f%% 12.345 [12.3%]

文字列・文字・真偽値(%s・%c・%b)

やりたいこと 指定子 入力 出力
そのまま %s "Java" [Java]
右寄せ(幅10) %10s "Java" [ Java]
左寄せ(幅10) %-10s "Java" [Java ]
先頭2文字だけ %.2s "Java" [Ja]
大文字にする %S "Java" [JAVA]
nullを渡す %s null [null]
1文字 %c 'A' [A]
文字コードから1文字 %c 65 [A]
真偽値 %b true [true]
真偽値にnull %b null [false]
真偽値に文字列 %b "false" [true](null以外はtrue)
ハッシュコード(16進) %h "Java" [231e42]

日付(%t)・その他

やりたいこと 指定子 入力 出力
年(4桁) %tY 2026-10-02T09:05:07 [2026]
月(2桁) %tm 同上 [10]
日(2桁) %td 同上 [02]
時(24時間・2桁) %tH 同上 [09]
分・秒 %tM・%tS 同上 [05]・[07]
年-月-日 %tF 同上 [2026-10-02]
時:分:秒 %tT 同上 [09:05:07]
時:分 %tR 同上 [09:05]
月名・曜日 %tB・%ta 同上 [Oct]・[Fri](ロケールで変わる)
引数の順番を指定 %2$s-%1$s "A", "B" [B-A]
同じ引数を使い回す %tY年%<tm月%<td日 日時1つ [2026年10月02日]
%そのもの %% なし [%]
改行(OSに合わせる) %n なし 改行

書式指定子の組み立て方は次の順番です。

%[引数の番号$][フラグ][幅][.精度]変換文字
例: %1$-10.2f → 1番目の引数を、左寄せ(-)、幅10、小数2桁、小数(f)で
部品 例 意味
引数の番号 1$・2$・< 何番目の引数を使うか。<は直前と同じ引数
フラグ - 0 , + 空白 ( # 左寄せ、0埋め、桁区切り、符号、空白、かっこ、0xなどの接頭辞
幅 10 最低の文字数。足りなければ空白(0フラグなら0)で埋める
精度 .2 %fでは小数の桁数、%sでは最大文字数
変換文字 d f s x c b e t % n 何として整形するか

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Java String.format書式一覧|0埋め・桁区切り・小数・左寄せ早見表」

早見表を出力したコード(コピペで確認できます)

上の早見表は、次のプログラムの出力から作っています。 入力を変えて試すと、書式の動きを確かめられます。Locale.ROOTを指定しているのは、実行するPCの言語設定で結果が変わらないようにするためです(理由は後半の「Locale」の章で説明します)。

import java.time.LocalDateTime;
import java.util.Locale;

public class FormatTable {
    static void show(String spec, Object arg) {
        // 結果を [ ] で囲んで空白を見えるようにする
        System.out.printf(Locale.ROOT, "%-10s %-14s [%s]%n", spec, String.valueOf(arg),
            String.format(Locale.ROOT, spec, arg));
    }

    public static void main(String[] args) {
        System.out.println("== 整数");
        show("%05d", 42);
        show("%,d", 1234567);
        show("%#x", 255);
        System.out.println("== 小数");
        show("%.2f", 3.14159);
        show("%.0f", 2.5);
        show("%,.2f", 1234567.891);
        System.out.println("== 文字列・文字・真偽値");
        show("%-10s", "Java");
        show("%.2s", "Java");
        show("%b", "false");
        System.out.println("== 日付(%t)");
        LocalDateTime t = LocalDateTime.of(2026, 10, 2, 9, 5, 7);
        show("%tF", t);
        System.out.println("== 引数の位置指定・その他");
        System.out.println("[" + String.format("%2$s-%1$s", "A", "B") + "]");
        System.out.println("[" + String.format("%tY年%<tm月%<td日", t) + "]");
        System.out.println("[" + String.format("100%%") + "]");
        System.out.println("[" + String.format("a%nb").replace(System.lineSeparator(), "(改行)") + "]");
    }
}

java FormatTable.javaで実行した結果(Java 21.0.10。表に載せた全項目はshow(...)の行を増やして確認しています):

== 整数
%05d       42             [00042]
%,d        1234567        [1,234,567]
%#x        255            [0xff]
== 小数
%.2f       3.14159        [3.14]
%.0f       2.5            [3]
%,.2f      1234567.891    [1,234,567.89]
== 文字列・文字・真偽値
%-10s      Java           [Java      ]
%.2s       Java           [Ja]
%b         false          [true]
== 日付(%t)
%tF        2026-10-02T09:05:07 [2026-10-02]
== 引数の位置指定・その他
[B-A]
[2026年10月02日]
[100%]
[a(改行)b]

早見表から読み取れる、つまずきやすい点です。

結果 理由と使い方
%.0fで2.5→3、%.2fで1.005→1.01 %fの丸めは四捨五入(HALF_UP)。後述のDecimalFormat(既定は偶数丸め)とは結果が変わる
%05dで-42→-0042 幅5には符号も含まれる
%bに"false"→true %bはnullならfalse、Boolean以外は中身に関係なくtrue
%.2sで"Java"→Ja %sの精度は「最大文字数」。長い文字列を切り詰めるのに使える
%xで-1→ffffffff 負のintは2の補数(32ビット)で表示される

0埋め・桁区切り・小数・左寄せのコピペ例

検索されることが多い4つの書式を、組み合わせも含めてまとめます。

やりたいこと コピペ用 結果
会員番号を6桁の0埋め String.format("%06d", 42) 000042
金額に桁区切り String.format("%,d円", 1980000) 1,980,000円
小数2桁で四捨五入 String.format("%.2f", 3.14159) 3.14
桁区切り+小数1桁 String.format("%,.1f", 12345.67) 12,345.7
左寄せで表を作る String.format("%-6s|%6d|", "pen", 120) pen | 120|
時刻を2桁で String.format("%02d:%02d", 9, 5) 09:05
パーセント String.format("%.1f%%", 12.345) 12.3%
16進カラーコード String.format("#%02X%02X%02X", 255, 128, 0) #FF8000

※表のセル内の|は表示上のエスケープで、コードでは|と書きます。

表形式の出力は、書式を定数にしておくと列がそろいます。

final String ROW = "%-6s|%6d|%8.2f%n";
System.out.print(String.format(ROW, "pen", 120, 98.5) + String.format(ROW, "note", 8, 1200.0));

実行結果(Java 21.0.10、既定ロケールは英語):

pen   |   120|   98.50
note  |     8| 1200.00

0埋めは数値(%d・%f)にしか使えません。 文字列を0で埋めたいとき("42"→"00042")は、String.format("%5s", s).replace(' ', '0')か、数値に変換してから%05dを使います。%05sと書くとFormatFlagsConversionMismatchExceptionになります。

formatted・printf・MessageFormat・DecimalFormatの使い分け

Javaには文字列を整形する方法がいくつかあり、「どこに出すか」「何を整えるか」で選びます。 同じ値を6通りで整形しました。

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.util.Locale;

public class Alternatives {
    public static void main(String[] args) {
        String name = "佐藤";
        int count = 1234;
        double rate = 0.125;

        // 1. String.format
        System.out.println("String.format : " + String.format("%sさん %,d件 %.1f%%", name, count, rate * 100));
        // 2. formatted(Java 15+)
        System.out.println("formatted     : " + "%sさん %,d件 %.1f%%".formatted(name, count, rate * 100));
        // 3. printf(そのまま出力。改行は %n)
        System.out.printf("printf        : %sさん %,d件 %.1f%%%n", name, count, rate * 100);
        // 4. MessageFormat({番号} で埋め込む。数値は自動で桁区切り)
        System.out.println("MessageFormat : " + MessageFormat.format("{0}さん {1}件 {2,number,percent}", name, count, rate));
        System.out.println("MessageFormat : " + MessageFormat.format("{0}さん {1,number,#}件 '{'そのまま'}' It''s", name, count));
        // 5. DecimalFormat(パターンで数値を整形)
        DecimalFormat df = new DecimalFormat("#,##0.00");
        System.out.println("DecimalFormat : " + df.format(1234567.891) + " / " + new DecimalFormat("000000").format(42)
            + " / " + new DecimalFormat("0.#").format(2.50));
        // 6. NumberFormat(ロケールに合った書式)
        System.out.println("NumberFormat  : " + NumberFormat.getInstance(Locale.JAPAN).format(1234567.891)
            + " / " + NumberFormat.getPercentInstance(Locale.JAPAN).format(rate)
            + " / " + NumberFormat.getCurrencyInstance(Locale.JAPAN).format(1980)
            + " / " + NumberFormat.getCompactNumberInstance(Locale.JAPAN, NumberFormat.Style.SHORT).format(12345678));

        // 丸め方の違い(2.5 と 0.125)
        System.out.println("丸め %.0f(2.5)            : " + String.format("%.0f", 2.5));
        System.out.println("丸め DecimalFormat(2.5)   : " + new DecimalFormat("0").format(2.5));
        System.out.println("丸め %.2f(0.125)          : " + String.format("%.2f", 0.125));
        System.out.println("丸め DecimalFormat(0.125) : " + new DecimalFormat("0.00").format(0.125));
        System.out.println("丸め BigDecimal HALF_UP   : " + new BigDecimal("0.125").setScale(2, RoundingMode.HALF_UP));
    }
}

実行結果(Java 21.0.10):

String.format : 佐藤さん 1,234件 12.5%
formatted     : 佐藤さん 1,234件 12.5%
printf        : 佐藤さん 1,234件 12.5%
MessageFormat : 佐藤さん 1,234件 12%
MessageFormat : 佐藤さん 1234件 {そのまま} It's
DecimalFormat : 1,234,567.89 / 000042 / 2.5
NumberFormat  : 1,234,567.891 / 12% / ¥1,980 / 1235万
丸め %.0f(2.5)            : 3
丸め DecimalFormat(2.5)   : 2
丸め %.2f(0.125)          : 0.13
丸め DecimalFormat(0.125) : 0.12
丸め BigDecimal HALF_UP   : 0.13

出力から読み取れるポイント:

  • String.format・formatted・printfは書式が共通で、結果も同じです。
  • MessageFormatの{1}は数値を自動で桁区切りします(1,234)。区切りたくないときは{1,number,#}と書きます。{をそのまま出すには'{'、'は''と2つ重ねます。
  • percentやNumberFormatのパーセントは12.5%が12%になりました。 小数以下を出さない設定で、偶数丸め(HALF_EVEN)で丸められるためです。
  • 丸め方が違います。 %.0fは2.5→3(四捨五入)、DecimalFormatは2.5→2(偶数丸め)。金額など丸め方を厳密に決めたい値は、BigDecimalのsetScale(桁, RoundingMode.HALF_UP)で明示するのが確実です(詳しくは「Java BigDecimalの使い方」の記事で解説しています)。
方法 書き方 得意なこと 選ぶ場面
String.format String.format("%05d", n) 書式指定子で何でも整形 基本はこれ
formatted(Java 15+) "%05d".formatted(n) String.formatと同じ。書式から書ける 短く書きたい、テキストブロックと組み合わせる
printf System.out.printf("%d%n", n) 整形してそのまま出力 標準出力・ファイル出力(PrintWriter)
MessageFormat MessageFormat.format("{0}件", n) 番号で埋め込む。語順の違う言語のメッセージ 多言語対応のメッセージ(ResourceBundleと組み合わせ)
DecimalFormat new DecimalFormat("#,##0.00") 数値専用のパターン。丸め方を指定できる 数値の表示形式を1つに決めて使い回す
NumberFormat NumberFormat.getCurrencyInstance(loc) ロケールに合った数値・通貨・パーセント・短縮表記 利用者の国・言語に合わせた表示
文字列連結 "合計" + n + "件" 整形不要の単純な連結 書式が要らないとき

formattedはJava 15で追加されたインスタンスメソッドで、String.format(this, args)と同じ結果になります。 変数に入れた書式やテキストブロックに続けて書けるのが利点です。

String tmpl = """
    会員番号: %06d
    氏名    : %s
    """;
System.out.print(tmpl.formatted(42, "佐藤"));

なお、DecimalFormatはスレッドセーフではないので、複数スレッドで共有する場合はスレッドごとに作るか、String.formatを使います。

Localeで結果が変わる(小数点がカンマになる例)

String.formatは、ロケール(言語・地域の設定)によって桁区切りや小数点の記号が変わります。 ロケールを省略すると、実行環境の既定ロケールが使われます。

import java.time.LocalDate;
import java.util.Locale;

public class LocaleDemo {
    public static void main(String[] args) {
        double v = 1234567.891;
        LocalDate d = LocalDate.of(2026, 10, 2);
        Locale[] locales = {Locale.ROOT, Locale.JAPAN, Locale.US, Locale.GERMANY, Locale.FRANCE};
        for (Locale loc : locales) {
            String s = String.format(loc, "%,.2f", v);
            System.out.printf("%-8s %-16s %-12s %s%n", loc.toLanguageTag(), "[" + s + "]",
                String.format(loc, "%tB", d), String.format(loc, "%ta", d));
        }
        // フランス語の桁区切りの文字を確認
        String fr = String.format(Locale.FRANCE, "%,d", 1234567);
        fr.codePoints().filter(c -> !Character.isDigit(c))
            .forEach(c -> System.out.printf("FRANCE の区切り文字: U+%04X%n", c));

        System.out.println("既定ロケール: " + Locale.getDefault());
        Locale.setDefault(Locale.GERMANY);
        String csv = String.format("%.2f,%.2f", 1.5, 2.25);
        System.out.println("GERMANY を既定にして CSV を作る: " + csv);
        System.out.println("Locale.ROOT を指定           : " + String.format(Locale.ROOT, "%.2f,%.2f", 1.5, 2.25));
        System.out.println("formatted も既定ロケール     : " + "%.2f".formatted(1.5));
        try {
            System.out.println("Double.parseDouble(\"1,50\") : " + Double.parseDouble(String.format("%.2f", 1.5)));
        } catch (NumberFormatException e) {
            System.out.println("Double.parseDouble で例外    : " + e);
        }
    }
}

実行結果(Java 21.0.10):

und      [1,234,567.89]   Oct          Fri
ja-JP    [1,234,567.89]   10月          金
en-US    [1,234,567.89]   October      Fri
de-DE    [1.234.567,89]   Oktober      Fr.
fr-FR    [1 234 567,89]   octobre      ven.
FRANCE の区切り文字: U+202F
FRANCE の区切り文字: U+202F
既定ロケール: en
GERMANY を既定にして CSV を作る: 1,50,2,25
Locale.ROOT を指定           : 1.50,2.25
formatted も既定ロケール     : 1,50
Double.parseDouble で例外    : java.lang.NumberFormatException: For input string: "1,50"

ドイツ語(de-DE)では小数点が,、桁区切りが.になり、フランス語(fr-FR)では桁区切りが空白に見える文字(U+202F:狭いノーブレークスペース)になりました。 この状態でCSVを作ると1,50,2,25となり、列の区切りと小数点の区別がつかなくなります。また、整形した文字列をDouble.parseDoubleに戻すとNumberFormatExceptionになります。

用途 指定するロケール 書き方
CSV・JSON・ログ・ファイル名など、プログラムが読む文字列 Locale.ROOT(記号を固定) String.format(Locale.ROOT, "%.2f", v)
画面に表示する、人が読む文字列 利用者のロケール String.format(userLocale, "%,.2f", v)
日本向けに固定して表示 Locale.JAPAN String.format(Locale.JAPAN, "%,d円", n)

formattedにはロケールを渡す引数がなく、常に既定ロケールを使います。 ロケールを固定したい場面ではString.format(Locale.ROOT, ...)を使ってください。日本語環境のPCでは問題が出なくても、サーバーやコンテナの既定ロケールが違うと結果が変わることがあります(この記事の実行環境の既定ロケールはenでした)。

全角文字で桁がずれる理由と直し方

%-10sの「幅10」は文字数(正確にはcharの数)で数えるため、画面で2列ぶんの幅を使う全角文字が入ると、表の列がずれます。

import java.util.List;

public class WideAlign {
    // 表示幅:半角=1、全角(ひらがな・カタカナ・漢字・全角記号など)=2 として数える簡易版
    static int width(String s) {
        int w = 0;
        for (int cp : s.codePoints().toArray()) {
            boolean wide = (cp >= 0x1100 && cp <= 0x115F)
                || (cp >= 0x2E80 && cp <= 0xA4CF)
                || (cp >= 0xAC00 && cp <= 0xD7A3)
                || (cp >= 0xF900 && cp <= 0xFAFF)
                || (cp >= 0xFE30 && cp <= 0xFE4F)
                || (cp >= 0xFF00 && cp <= 0xFF60)
                || (cp >= 0xFFE0 && cp <= 0xFFE6)
                || (cp >= 0x1F300 && cp <= 0x1FAFF)
                || (cp >= 0x20000 && cp <= 0x3FFFD);
            w += wide ? 2 : 1;
        }
        return w;
    }

    static String padRight(String s, int cols) {
        return s + " ".repeat(Math.max(0, cols - width(s)));
    }

    static String padLeft(String s, int cols) {
        return " ".repeat(Math.max(0, cols - width(s))) + s;
    }

    record Row(String name, int stock) {}

    public static void main(String[] args) {
        List<Row> rows = List.of(new Row("pen", 120), new Row("ボールペン", 8), new Row("ノートA4", 45));

        System.out.println("-- %-10s だけ(全角が2列ぶん表示されてずれる)");
        for (Row r : rows) {
            System.out.println(String.format("%-10s|%5d|", r.name(), r.stock()));
        }
        System.out.println("-- 表示幅で埋める");
        for (Row r : rows) {
            System.out.println(padRight(r.name(), 10) + "|" + String.format("%5d", r.stock()) + "|");
        }
        System.out.println("length と表示幅: " + "ボールペン".length() + " / " + width("ボールペン"));
        System.out.println("右寄せの例: [" + padLeft("在庫", 8) + "]");
    }
}

実行結果(Java 21.0.10。等幅フォントの端末で表示した場合):

-- %-10s だけ(全角が2列ぶん表示されてずれる)
pen       |  120|
ボールペン     |    8|
ノートA4     |   45|
-- 表示幅で埋める
pen       |  120|
ボールペン|    8|
ノートA4  |   45|
length と表示幅: 5 / 10
右寄せの例: [    在庫]

"ボールペン"はlength()が5ですが、画面では10列ぶんの幅を使います。 %-10sは5文字ぶんの空白を足すので、合計15列になって右にずれます。表示幅(半角1・全角2)を数えて空白を足すと、列がそろいました。

方法 内容 注意点
表示幅を数えて埋める(上のコード) 全角を2として空白を追加 簡易版。結合文字や一部の記号・絵文字は端末やフォントで幅が変わる
全角スペースで埋める 全角の項目だけ全角スペースで埋める 半角と全角が混ざると合わない
表示をHTMLの表やCSVにする 列ぞろえを表示側に任せる 画面表示ならこちらが確実

文字幅の判定は、Unicodeの「East Asian Width」という分類に沿っています。 正確に判定したい場合は、この分類に対応したライブラリを使うか、出力先(HTML・Excel・CSV)で列をそろえる方法がおすすめです。

よくある例外の再現と直し方

String.formatの例外は、ほとんどが「指定子と引数の数・型が合っていない」ことが原因です。 よく見る例外をまとめて再現しました。

public class FormatErrors {
    static void tryFormat(String label, String fmt, Object... args) {
        try {
            System.out.println(label + " -> " + String.format(fmt, args));
        } catch (Exception e) {
            System.out.println(label + " -> " + e);
        }
    }

    public static void main(String[] args) {
        tryFormat("引数が足りない     %s %s", "%s %s", "A");
        tryFormat("型が違う           %d に 3.14", "%d", 3.14);
        tryFormat("型が違う           %d に \"42\"", "%d", "42");
        tryFormat("型が違う           %.2f に 5", "%.2f", 5);
        tryFormat("知らない変換       %i", "%i", 1);
        tryFormat("% の後が空白なし   50%", "50%", 1);
        tryFormat("フラグの矛盾       %-05d", "%-05d", 1);
        tryFormat("幅がない           %-d", "%-d", 1);
        tryFormat("%x に , フラグ     %,x", "%,x", 255);
        tryFormat("%s に精度 OK        %.1s", "%.1s", "abc");
        tryFormat("%d に精度          %.2d", "%.2d", 1);
        tryFormat("引数が多い(例外なし)", "%s", "A", "B");
        tryFormat("%d に BigDecimal   ", "%d", new java.math.BigDecimal("1"));
        tryFormat("%f に BigDecimal   ", "%.3f", new java.math.BigDecimal("0.1"));
        tryFormat("%d に long          ", "%d", Long.MAX_VALUE);
    }
}

実行結果(Java 21.0.10):

引数が足りない     %s %s -> java.util.MissingFormatArgumentException: Format specifier '%s'
型が違う           %d に 3.14 -> java.util.IllegalFormatConversionException: d != java.lang.Double
型が違う           %d に "42" -> java.util.IllegalFormatConversionException: d != java.lang.String
型が違う           %.2f に 5 -> java.util.IllegalFormatConversionException: f != java.lang.Integer
知らない変換       %i -> java.util.UnknownFormatConversionException: Conversion = 'i'
% の後が空白なし   50% -> java.util.UnknownFormatConversionException: Conversion = '%'
フラグの矛盾       %-05d -> java.util.IllegalFormatFlagsException: Flags = '-0'
幅がない           %-d -> java.util.MissingFormatWidthException: %-d
%x に , フラグ     %,x -> java.util.FormatFlagsConversionMismatchException: Conversion = x, Flags = ,
%s に精度 OK        %.1s -> a
%d に精度          %.2d -> java.util.IllegalFormatPrecisionException: 2
引数が多い(例外なし) -> A
%d に BigDecimal    -> java.util.IllegalFormatConversionException: d != java.math.BigDecimal
%f に BigDecimal    -> 0.100
%d に long           -> 9223372036854775807

tryで囲まずにString.format("%d件", 3.5)を実行すると、次のスタックトレースになります(1行だけのプログラムErrTrace.javaで確認)。

Exception in thread "main" java.util.IllegalFormatConversionException: d != java.lang.Double
    at java.base/java.util.Formatter$FormatSpecifier.failConversion(Formatter.java:4515)
    at java.base/java.util.Formatter$FormatSpecifier.printInteger(Formatter.java:3066)
    at java.base/java.util.Formatter$FormatSpecifier.print(Formatter.java:3021)
    at java.base/java.util.Formatter.format(Formatter.java:2791)
    at java.base/java.util.Formatter.format(Formatter.java:2728)
    at java.base/java.lang.String.format(String.java:4379)
    at ErrTrace.main(ErrTrace.java:1)

d != java.lang.Doubleは「%dにDoubleが渡された」という意味です。 自分のコードの行(ErrTrace.main)はスタックトレースの一番下にあります。

例外 原因 直し方
MissingFormatArgumentException 指定子の数より引数が少ない 引数を足す。同じ値を使い回すなら%1$sや%<s
IllegalFormatConversionException: d != java.lang.Double %dに小数を渡した %.0fにするか、(long) vやMath.round(v)で整数にする
IllegalFormatConversionException: f != java.lang.Integer %fに整数を渡した %dにするか、(double) nに変換
IllegalFormatConversionException: d != java.lang.String 数値の書式に文字列を渡した Integer.parseInt(s)で数値にしてから渡す
UnknownFormatConversionException: Conversion = 'i' 存在しない変換文字(Cの%iなど) %dを使う
UnknownFormatConversionException: Conversion = '%' %を1つだけ書いた %%と2つ重ねる
IllegalFormatFlagsException: Flags = '-0' 左寄せと0埋めの同時指定 どちらかにする(0埋めは右寄せのみ)
MissingFormatWidthException -や0フラグに幅がない %-5dのように幅を書く
FormatFlagsConversionMismatchException 変換に使えないフラグ(%,x、%05sなど) フラグを外す
IllegalFormatPrecisionException 整数に精度を指定(%.2d) 精度を外す、または%05dで桁をそろえる

引数が多すぎる場合は例外にならず、余った引数は無視されます。 書式の書き間違いに気づきにくいので、テストで出力を確認しておくと安心です。

%dにはint・long・BigInteger、%fにはdouble・float・BigDecimalを渡します。 BigDecimalは%dでは例外になりますが、%.3fなら誤差なく0.100と表示されました。

日付はDateTimeFormatterがおすすめ

%tYなどの%t系でも日付を整形できますが、日付の表示はDateTimeFormatterを使う方が読みやすく、書式も柔軟です。

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Locale;

public class DateFmt {
    public static void main(String[] args) {
        LocalDateTime t = LocalDateTime.of(2026, 10, 2, 9, 5, 7);
        System.out.println("%t の組み合わせ   : " + String.format("%1$tY/%1$tm/%1$td %1$tH:%1$tM", t));
        DateTimeFormatter f = DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm");
        System.out.println("DateTimeFormatter : " + t.format(f));
        System.out.println("曜日つき(日本語) : " + t.format(DateTimeFormatter.ofPattern("M月d日(E)", Locale.JAPAN)));
        System.out.println("文字列へ埋め込む   : " + "更新日時: %s".formatted(t.format(f)));
        try {
            System.out.println(String.format("%tY", "2026-10-02"));
        } catch (Exception e) {
            System.out.println("%tY に文字列       : " + e);
        }
        System.out.println("%tY に long(ミリ秒): " + String.format("%tY", 0L));
        System.out.println("%tY に Date        : " + String.format("%tY", new Date(0L)));
    }
}

実行結果(Java 21.0.10):

%t の組み合わせ   : 2026/10/02 09:05
DateTimeFormatter : 2026/10/02 09:05
曜日つき(日本語) : 10月2日(金)
文字列へ埋め込む   : 更新日時: 2026/10/02 09:05
%tY に文字列       : java.util.IllegalFormatConversionException: Y != java.lang.String
%tY に long(ミリ秒): 1970
%tY に Date        : 1970
観点 %t系(String.format) DateTimeFormatter
書き方 %1$tY/%1$tm/%1$td(同じ引数を何度も指定) uuuu/MM/dd(パターン1つ)
0なしの月日(10月2日) 書式だけではできない M月d日で書ける
文字列から日付への変換(パース) できない LocalDate.parse(s, f)でできる
使い回し 毎回書式を解析 不変・スレッドセーフで定数にできる
受け付ける型 long・Date・Calendar・TemporalAccessor LocalDateなどのjava.timeの型

%t系は文字列を渡すとIllegalFormatConversionExceptionになり、longはエポックミリ秒(1970年からのミリ秒)として解釈されます。 日付の整形・計算・タイムゾーンの扱いは「Javaの日付処理|LocalDateTimeの使い方と7つの落とし穴」の記事で詳しく解説しているので、あわせて参照してください。

Java 25について:手元の環境はJava 21.0.10のため、Java 22〜25では実行していません。公式のAPI差分一覧(Java SE 25の「New API」)を確認したところ、java.util.FormatterとString.format/formattedに追加されたメソッドはありませんでした。この記事の書式指定子はJava 25でもそのまま使えます。

よくある質問

Q. Javaで数値を0埋めするにはどう書きますか? A. String.format("%05d", n)で5桁の0埋めになります。 Java 15以降なら"%05d".formatted(n)とも書けます。負の数は-0042のように符号も桁数に含まれます。文字列を0埋めするときはString.format("%5s", s).replace(' ', '0')を使います。

Q. 小数点以下の桁数を指定して四捨五入するには? A. String.format("%.2f", v)で小数2桁に四捨五入(HALF_UP)されます。 DecimalFormatの既定は偶数丸め(2.5→2)なので結果が変わることがあります。丸め方を明示したい場合はBigDecimal.setScale(2, RoundingMode.HALF_UP)を使います。

Q. String.formatとformattedはどちらを使えばよいですか? A. 結果は同じなので、Java 15以降なら読みやすい方で構いません。 ロケールを指定したいときは、引数にロケールを渡せるString.format(Locale.ROOT, ...)を使います。

Q. String.formatは遅いですか? A. 書式を解析するぶん、単純な文字列連結よりは処理が多くなります。 1件ずつの表示やログでは気にならないことがほとんどです。大量のループの中で使う場合は、StringBuilderでの連結と比べて、実際の処理時間を測って判断してください。

まとめ

  • 0埋めは%05d、桁区切りは%,d、小数2桁は%.2f、左寄せは%-10s、右寄せは%10s
  • 書式は%[番号$][フラグ][幅][.精度]変換文字の順。%そのものは%%、改行は%n
  • String.format・formatted(Java 15+)・printfは同じ書式。メッセージはMessageFormat、数値の定型表示はDecimalFormat/NumberFormat
  • %.2fは四捨五入、DecimalFormatは偶数丸め。丸め方を決めたい値はBigDecimalで
  • ロケールで記号が変わる(ドイツ語は1.234.567,89)。プログラムが読む文字列はLocale.ROOTを指定
  • 全角文字は幅2で表示されるため%-10sではずれる。表示幅を数えて埋める
  • 例外の多くは指定子と引数の数・型の不一致。日付はDateTimeFormatterがおすすめ

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Java String.format書式一覧|0埋め・桁区切り・小数・左寄せ早見表」

株式会社RJCでは、String.formatのような日々使う書き方の細かな動きを、仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?