Javaで文字列の一部を置換する場合には、replaceや正規表現での置換を用いたりしますが、エラーメッセージなど、定型の文字列の一部を渡したパラメータで置き換える形で生成するには、MessageFormatクラスを使うと便利です。
特に、置き換える元の文字列は、
「エラーコード:{0} エラー理由:{1}
のように設定しておけるので、プロパティ・ファイルなど、プログラムの外部に保持して、比較的自由に変更することができます。
MessageFormatで文字列をフォーマット(置換)する2つの方法と使い分け
MessageFormatは2つの使い方があります。
staticなメソッドを使う方法とインスタンスを生成して同じテンプレートを使いまわす方法です。
staticなメソッドを使う方法では、format()が呼ばれたときに、内部的には一回限りの目的のために MessageFormat インスタンスを生成しています。
String template = "Hello! {0}さん。{1}も元気?";
Object[] params = {"太郎","花子"};
String message = MessageFormat.format(template, params);
System.out.println(message);
一方、インスタンスを生成する方は、その生成時にテンプレートの文字列を引数に取りますので、そのテンプレートに対して、異なるパラメータを渡すことができます。
そのため、繰り返す際のパフォーマンスには優れていますね。
MessageFormat mf = new MessageFormat("エラーコード:{0} エラー理由:{1}");
String[] params2 = {"E-112", "不正な文字列です。"};
String[] params3 = {"E-113", "文字列が空です。"};
String[] params4 = {"E-114", "セッションが不正です。"};
System.out.println(mf.format(params2));
System.out.println(mf.format(params3));
System.out.println(mf.format(params4));
ちょっとしたフォーマットのTips
MessageFormatは、その名の通り、メッセージ出力のためにフォーマットを指定して表示できるクラスで、文字列だけがそのフォーマット対象ではありません。数字や日付もフォーマット指定して出力できます。
数字も出力可能ですが、デフォルトのフォーマット指定だと、数字が千桁以上になるとカンマがついて出力されます。これを、カンマ無しで表示するには、以下のように「#」を指定しましょう。
MessageFormat mfNo = new MessageFormat("数字そのまま{0} or カンマなし:{1,number,#}");
Integer[] paramsNo = {123456,123456};
System.out.println(mfNo.format(paramsNo));
上記の数字フォーマットを応用すると、数字の左側を0埋めして「00001」のように出力することもできます。
MessageFormat mfNo2 = new MessageFormat("0埋め数字{0,number,0000}");
Integer[] paramsNo2 = {1};
System.out.println(mfNo2.format(paramsNo2));
同じことを別のクラス(String.format)でやるとしたら、
String str = String.format("%05d", 1);
System.out.println(str);
のようにも書くことができます。
よくファイルのネーミングやログの出力時の参考に「YYYYMMDD」の形式の文字列が欲しくなることがありますが、そんなこともできます。
MessageFormat mfDay = new MessageFormat("こんにちは。今日は{0,date,yyyy年MM月dd日}、時刻は{0,time}です。数字だけにすると、{0,date,yyyyMMdd}、時刻は{0,time,HHMMSS}です。");
Object[] paramsDay = {new Date(System.currentTimeMillis())};
System.out.println(mfDay.format(paramsDay));
同じことをSimpleDateFormatでやるとしたら
Date date = new Date();
String dateStr = new SimpleDateFormat("yyyyMMddhhmmss").format(date);
System.out.println(dateStr);
のようにも書けますね。
{0,date,yyyy年MM月dd日}のようにフォーマット形式を指定していますが、0(添え字)の次のひとつめ(date)はフォーマット・タイプ、2つ目(yyyy年MM月dd日)はフォーマット・スタイル(サブフォーマット・パターン)と言って、フォーマットのより詳しい形式を指定しています。
全部使ったMessageFormatのサンプルソース
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Sample1 {
public static void main(String[] args) {
//staticなメソッドを使う方法
String template = "Hello! {0}さん。{1}も元気?";
Object[] params = {"太郎","花子"};
String message = MessageFormat.format(template, params);
System.out.println(message);
//インスタンスを生成する方法
MessageFormat mf = new MessageFormat("エラーコード:{0} エラー理由:{1}");
String[] params2 = {"E-112", "不正な文字列です。"};
String[] params3 = {"E-113", "文字列が空です。"};
String[] params4 = {"E-114", "セッションが不正です。"};
System.out.println(mf.format(params2));
System.out.println(mf.format(params3));
System.out.println(mf.format(params4));
//数字のフォーマット
MessageFormat mfNo = new MessageFormat("数字そのまま{0} or カンマなし:{1,number,#}");
Integer[] paramsNo = {123456,123456};
System.out.println(mfNo.format(paramsNo));
String str = String.format("%05d", 1);
System.out.println(str);
//0埋め(パディング)
MessageFormat mfNo2 = new MessageFormat("0埋め数字{0,number,0000}");
Integer[] paramsNo2 = {1};
System.out.println(mfNo2.format(paramsNo2));
//日付と時間の変換
MessageFormat mfDay = new MessageFormat("こんにちは。今日は{0,date,yyyy年MM月dd日}、時刻は{0,time}です。数字だけにすると、{0,date,yyyyMMdd}、時刻は{0,time,HHMMSS}です。");
Object[] paramsDay = {new Date(System.currentTimeMillis())};
System.out.println(mfDay.format(paramsDay));
Date date = new Date();
String dateStr = new SimpleDateFormat("yyyyMMddhhmmss").format(date);
System.out.println(dateStr);
}
}