Java 入門

Java printf によるフォーマット出力

フォーマット出力(Formatted Output)は、Javaプログラミングにおいてデータをクリアで読みやすく、かつプロフェッショナルな形式で表示するための重要なスキルです。printf メソッド(および関連するフォーマット機能)を使用することで、数値、日付、文字列、その他のデータ型の表示方法を精密に制御できます。

本章では printf の詳細を深く掘り下げ、さまざまなアプリケーションで洗練された出力を生成するためのツールを提供します。前章のコンソール出力の知識をベースにしつつ、後続の章で扱うファイルへのデータ書き込みに向けた準備を整えていきましょう。

1. printf の理解

printf メソッドは C言語から継承されたもので、Java に強力なフォーマット出力機能を提供します。これは、文字列内に「書式指定子(Format Specifiers)」を埋め込み、それを対応する引数(パラメータ)で置き換えるという仕組みです。

基本的な構文は以下の通りです:

System.out.printf(書式文字列, 引数1, 引数2, ...);
  • 書式文字列 (formatString): リテラルテキストと書式指定子を含む文字列。
  • 引数1, 引数2, ...: フォーマットされて書式文字列に挿入されるパラメータ。引数の数と型は、書式指定子と一致している必要があります。

println メソッドに慣れている方なら、printf がより高度な制御を提供していることに気づくでしょう。単に値を文字列として連結するのではなく、出力のスタイルを厳密に指定できます。

2. 書式指定子

書式指定子はパーセント記号(%)で始まり、データ型を示す「変換文字」で終わります。以下はよく使われる変換文字です:

変換文字データ型説明
%dint, byte, short, long整数を10進数としてフォーマットします。
%ffloat, double浮動小数点数を10進数としてフォーマットします。
%sString文字列をフォーマットします。
%cchar文字をフォーマットします。
%bbooleanboolean値を "true" または "false" としてフォーマットします。
%n(なし)プラットフォーム固有の改行コードを挿入します。クロスプラットフォーム互換性のため、\n より %n が推奨されます。
%%(なし)リテラルのパーセント記号(%)を出力します。

コード例:

int quantity = 10;
double price = 2.50;
String item = "りんご";

System.out.printf("%d個の%sがあり、価格は1個あたり$%.2fです。%n", quantity, item, price);
// 出力: 10個のりんごがあり、価格は1個あたり$2.50です。

この例では:

  • %dquantity の値 (10) に置き換わります。
  • %sitem の値 ("りんご") に置き換わります。
  • %.2fprice の値 (2.50) に置き換わり、小数点以下2桁でフォーマットされます。
  • %n で改行が挿入されます。

3. フラグ、幅、精度

書式指定子には、出力をさらにカスタマイズするために「フラグ」「幅」「精度」の修飾子を含めることができます。完全な構文は以下の通りです:

%[フラグ][幅][.精度]変換文字

3.1 フラグ (Flags)

出力形式を修正するために使用します。主なフラグは以下の通りです:

  • - (左揃え): 指定された幅の中で左寄せに出力します。
  • + (符号表示): 数値に対して常に正負の符号(+ または -)を表示します。
  • 0 (ゼロ埋め): 指定された幅に達するまで、先頭をゼロで埋めます。
  • , (グループ区切り文字): ロケール固有の区切り文字(例:日本や米国ではカンマ)を数値に使用します。
  • (スペース): + フラグがない正の数の前にスペースを1つ追加します。

3.2 幅 (Width)

出力する最小文字数を指定します。値の長さが幅より短い場合は、スペース(または 0 フラグ使用時はゼロ)で埋められます。

3.3 精度 (Precision)

浮動小数点数の小数点以下の桁数、または文字列出力の最大文字数を指定します。

コード例:

int number = 123;
double value = 1234.5678;
String text = "Hello";

System.out.printf("幅6の数字: %6d%n", number);             // 出力: "   123"
System.out.printf("ゼロ埋め数字: %06d%n", number);          // 出力: "000123"
System.out.printf("精度2の数値: %.2f%n", value);           // 出力: "1234.57" (四捨五入されます)
System.out.printf("区切り文字付き数値: %,f%n", value);      // 出力: "1,234.567800" (地域設定に依存)
System.out.printf("左揃えテキスト: %-10s!%n", text);       // 出力: "Hello     !"

4. 日付と時刻のフォーマット

printf は、特別な変換文字を使用して日付や時刻の値をフォーマットすることもサポートしています。これらの指定子は %t で始まります。

変換文字説明例 (現在の日付に基づく)
%tDMM/DD/YY 形式03/15/26
%tFYYYY-MM-DD 形式2026-03-15
%tTHH:MM:SS 形式 (24時間制)14:30:45
%trAM/PM 付きの時間形式02:30:45 PM
%tA曜日のフルネーム金曜日 (ロケールに依存)
%tB月のフルネーム3月
%tY4桁の年2026

コード例:

import java.util.Date;

public class DateFormatExample {
    public static void main(String[] args) {
        Date today = new Date();
        
        // < フラグを使用して直前の引数を再利用する
        System.out.printf("今日は: %tA, %tB %td, %tY%n", today, today, today, today);
        // 出力例: 今日は: 金曜日, 3月 15, 2026
                
        System.out.printf("現在時刻: %tr%n", today);
    }
}

テクニック: 同じ書式文字列内で同じ日付オブジェクトを何度も使用する場合、1$ のような形式や < フラグを使うと引数を繰り返し書く手間が省けます。
System.out.printf("%1$tA, %1$tB %1$td, %1$tY%n", today);
ここで 1$ は1番目の引数を参照することを意味します。

5. 引数インデックス

引数インデックスを使用すると、引数が使用される順序を明示的に指定できます。引数インデックスは整数の後に $ 記号を続けます。例えば、%2$d は2番目の引数を指し、%3$s は3番目の引数を指します。

String firstName = "太郎";
String lastName = "山田";

// 出力: 山田, 太郎
System.out.printf("%2$s, %1$s%n", firstName, lastName);

6. 実践的な活用ケース

6.1 ケース 1:テーブル出力のフォーマット

価格と数量を含む製品リストを表示します。

public class ProductTable {
    public static void main(String[] args) {
        String[] products = {"ノートPC", "マウス", "キーボード", "モニター"};
        double[] prices = {1200.00, 25.50, 75.00, 300.75};
        int[] quantities = {5, 20, 10, 7};

        System.out.printf("%-12s %8s %8s%n", "商品名", "価格", "数量");
        System.out.println("----------------------------------");

        for (int i = 0; i < products.length; i++) {
            System.out.printf("%-12s %8.2f %8d%n", products[i], prices[i], quantities[i]);
        }
    }
}

6.2 ケース 2:ロケール設定による通貨フォーマット

java.util.Locale を使用して、異なる地域の標準に従って金額をフォーマットします。

import java.util.Locale;

public class CurrencyFormatting {
    public static void main(String[] args) {
        double amount = 1234.56;
        
        // 米国ドル形式
        System.out.printf(Locale.US, "米国: $%,.2f%n", amount);
        
        // ドイツユーロ形式
        System.out.printf(Locale.GERMANY, "ドイツ: %,.2f €%n", amount);
        
        // 日本円形式(整数表示が一般的)
        System.out.printf(Locale.JAPAN, "日本: ¥%,.0f%n", amount);
    }
}