ジェネリクスについて調べていたら、printf()メソッドに遭遇しました。
System.out.println()やSystem.out.print()はなじみがあったのですが、System.out.printf()ははじめてみましたし、書き方も理解できなかったので調べてみました。
printf()メソッドとは
printf()メソッドはprintln()やprint()同様、コンソールやログに文字を出力するためのメソッドです。
printf()の特徴は出力する形式(format/フォーマット)を整えられる点です。
構文
引数は2つ目からはオプションです。
System.out.printf(フォーマット, 引数1, 引数2, 引数3…)
簡単に書くと以下のようになります。
System.out.printf(“%s”, “Hello World”);
あまり使われているのを見ませんが以下の構文もあります。
System.out.printf(ロケール, フォーマット, 引数1, 引数2, 引数3…);
こちらも引数は2つ目からはオプションです。
フォーマットのルール
構文のフォーマットにあたる部分の説明です。
書式指定子(Format specifiers)と呼ばれ、フラグ(flags), 幅(width), 制度(precision), 変換文字(conversion characters)が含まれます。
書き方
%[フラグ], [幅], [.制度], 変換文字
フォーマットのパラメータは「%」からはじまります。
後述するサンプルコードで使い方を説明します。
※[]で書かれているものはオプションです。
変換文字(conversion characters)について
変換文字は必須項目なので比較的よく見かけるパラメータを紹介しておきます。
- s – 文字列形式
- d – 数値形式(10進数)
- f – 小数点数形式
- t – 日付/時間形式
- b – 真偽値形式
上記はほんの一部です。変換文字やフラグなどのその他項目については以下でまとめられているのでそちらをご確認ください。
https://docs.oracle.com/javase/jp/8/docs/api/java/util/Formatter.html
printf() サンプルコード
変換文字とフラグ(flags), 幅(width), 制度(precision)などの理解を深めるためそれらを使用したサンプルコードを用意しました。
改行
%nで改行させることができます。
System.out.printf(“Programmer%nLife”);
実行結果
Programmer
Life
printf()メソッドは改行しないため最後に「%n」を使用されていることがよくあります。
例:System.out.printf(“Programmer Life%n”);
文字列形式(s)と幅(width)を使用したサンプルコード
幅(width)では最小文字数を指定できます。
System.out.printf(“‘%20s'”, “Programmer Life”);
結果
‘ Programmer Life’
最小文字列幅を20にしたため、”内が20文字になるようにスペースが入っています。
文字列形式(s)と幅(width)とフラグを使用したサンプルコード
上記のコードに左詰めフラグ「-」を使用しています。
System.out.printf(“‘%-20s'”, “Programmer Life”);
結果
‘Programmer Life ‘
フラグにより文字が左詰めに変更されています。フラグは他にも「0」で0埋めなどがあります。
数値形式(d)と複数の引数
引数は左から順に変換文字(conversion characters)へ埋められていきます。
System.out.printf(“4つの引数: %d, %d, %d, %d”,1, 2, 3, 4 );
結果
4つの引数: 1, 2, 3, 4
%dだけでなく%sなど他の変換文字が入ることも可能です。
例:System.out.printf(“4つの引数: %d, %d, %s, %d”,1, 2, “三”, 4 );
小数点数形式(f)と精度
小数点と精度を使用し小数点以下を指定します。
System.out.printf(“小数点第2位まで: %.2f”, 1.123456);
結果
1.12
とても便利に感じます。
日付/時間形式(T)
日付/時間形式の「T」は「t」も可能です。
System.out.printf(“%tT”, new Date());
System.out.printf(“%tH”, new Date());
System.out.printf(“%tM”, new Date());
結果
12:45:41
12
45
(実行時の時間)
「T」は「%tH:%tM:%tS」として24時間制で書式設定された時刻を表します。時間だけをぬきとりたい場合は「H」(00 – 23)、分は「M」と細かい単位で取得することも可能です。
日付/時間形式(T)とロケール
2つめの構文ロケールを使った例もせっかくなので紹介します。(引数が同じなのでもしかしたらもっといい書き方があるかもしれませんが。。。)
Date date = new Date();
System.out.printf(new Locale(“en”, “En”), “%TT%tp%n”, date, date);
System.out.printf(new Locale(“ja”, “Jp”), “%TT%tp%n”, date, date);
結果
12:50:13pm
12:50:13午後
ロケールを使ったメソッドをあまり知らないのですが時間表記など便利そうです。
真偽値形式(b)
真偽値を返す形式です。
※結果はコメントアウトに記入しています。
String str = null;
System.out.printf(“%b%n”, str); // false
System.out.printf(“%B%n”, false); // FALSE
System.out.printf(“%B%n”, 5.3); // TRUE
System.out.printf(“%b%n”, “random text”); //true
真偽値は以下のルールでtrue/falseを返します。
- 引数がnullの場合、結果は「false」になります。
- true/falseはString.valueOf(arg)により返される文字列となります。
- それ以外はすべてtrueとなります。
最大値を取り出すサンプルコード
少しだけ実用的な書き方です。
public class Test {
// 3つの要素から最大値を調べる
public static <T extends Comparable<T>> T maximum(T x, T y, T z) {
T max = x; // 仮でxを最大値に代入
if(y.compareTo(max) > 0) {
max = y; // yを最大値へ代入
}
if(z.compareTo(max) > 0) {
max = z; // zを最大値へ代入
}
return max; // 最大値を持ったオブジェクトを戻す
}
public static void main(String args[]) {
System.out.printf(“最大値は%d\n”, maximum( 3, 4, 5 ));
System.out.printf(“最大値は%.1f\n”, maximum( 6.6, 8.8, 7.7 ));
}
}
結果
最大値は5
最大値は8.8
例外 : MissingFormatArgumentException
引数の数に対して 変換文字(conversion characters)が多い場合は「MissingFormatArgumentException 」が発生します。
System.out.printf(“2つの引数: %d, %d, %d”,1, 2); // MissingFormatArgumentException
おわり
小数点など便利だなと思うこともあるけれどprintf()をつかわなくても「name + “さん”」 などの書き方でもいいんじゃないかと思ってしまいます。メモリなどの問題があるんでしょうか。
さほど難しくは感じませんが、時間の形式「H」やフラグ「-」など初見ではどういう意味かわからないので慣れるまでは使うのに抵抗を感じてしまいます。
参考:https://www.baeldung.com/java-printstream-printf