java.text.MessageFormat类
MessageFormat提供一种语言无关的方式来组装消息,它允许你在运行时刻用指定的参数来替换掉消息字符串中的一部分。你可以为MessageFormat定义一个模式,在其中你可以用占位符来表示变化的部分:

  1. import java.text.MessageFormat;
  2. import java.util.Date;
  3.  
  4. public class MessageFormatTest {
  5. public static void main(String[] args) {
  6. Object[] arguments = {
  7. 7,
  8. new Date(System.currentTimeMillis()),
  9. "a disturbance in the Force"
  10. };
  11. String result = MessageFormat.format(
  12. "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
  13. arguments);
  14. System.out.println(result);
  15. //output:
  16. // At 14:08:27 on 2017-7-7, there was a disturbance in the Force on planet 7.
  17. }
  18. }

占位符的格式为{ ArgumentIndex , FormatType , FormatStyle },详细说明可以参考MessageFormat的API说明文档。这里我们定义了两个占位符,其中的数字对应于传入的参数数组中的索引,{0}占位符被第一个参数替换,{1}占位符被第二个参数替换,依此类推。
最多可以设置10个占位符,而且每个占位符可以重复出现多次,而且格式可以不同,比如{1,date}和{1,time},{1,number,#.##}。而通过将这些模式定义放到不同的资源文件中,就能够根据不同的locale设置,得到不同的模式定义,并用参数动态替换占位符。
步骤:
1、找出可变的部分,并据此定义模式,将模式放入不同的资源文件中。
2、创建MessageFormat对象,并设置其locale属性。
MessageFormat formatter = new MessageFormat("");
formatter.setLocale(currentLocale);
3、从资源包中得到模式定义,以及设置参数。
messages = ResourceBundle.getBundle(
"i18n.resource.MessagesBundle",currentLocale);
Object[] arguments= {new Long(3), "MyDisk"};;
4、利用模式定义和参数进行格式化。
String result = MessageFormat.format(messages.getString(key), arguments);

http://blog.csdn.net/turkeyzhou/article/details/4487917

注意:
参数为Number类型Date类型时,会被格式化。数字会转换成科学计数法,譬如 123456,会format成 123,456
java.text.MessageFormat#subformat

  1. /**
  2. * Internal routine used by format. If <code>characterIterators</code> is
  3. * non-null, AttributedCharacterIterator will be created from the
  4. * subformats as necessary. If <code>characterIterators</code> is null
  5. * and <code>fp</code> is non-null and identifies
  6. * <code>Field.MESSAGE_ARGUMENT</code>, the location of
  7. * the first replaced argument will be set in it.
  8. *
  9. * @exception IllegalArgumentException if an argument in the
  10. * <code>arguments</code> array is not of the type
  11. * expected by the format element(s) that use it.
  12. */
  13. private StringBuffer subformat(Object[] arguments, StringBuffer result,
  14. FieldPosition fp, List<AttributedCharacterIterator> characterIterators) {
  15. // note: this implementation assumes a fast substring & index.
  16. // if this is not true, would be better to append chars one by one.
  17. int lastOffset = 0;
  18. int last = result.length();
  19. for (int i = 0; i <= maxOffset; ++i) {
  20. result.append(pattern.substring(lastOffset, offsets[i]));
  21. lastOffset = offsets[i];
  22. int argumentNumber = argumentNumbers[i];
  23. if (arguments == null || argumentNumber >= arguments.length) {
  24. result.append('{').append(argumentNumber).append('}');
  25. continue;
  26. }
  27. // int argRecursion = ((recursionProtection >> (argumentNumber*2)) & 0x3);
  28. if (false) { // if (argRecursion == 3){
  29. // prevent loop!!!
  30. result.append('\uFFFD');
  31. } else {
  32. Object obj = arguments[argumentNumber];
  33. String arg = null;
  34. Format subFormatter = null;
  35. if (obj == null) {
  36. arg = "null";
  37. } else if (formats[i] != null) {
  38. subFormatter = formats[i];
  39. if (subFormatter instanceof ChoiceFormat) {
  40. arg = formats[i].format(obj);
  41. if (arg.indexOf('{') >= 0) {
  42. subFormatter = new MessageFormat(arg, locale);
  43. obj = arguments;
  44. arg = null;
  45. }
  46. }
  47. } else if (obj instanceof Number) {
  48. // format number if can
  49. subFormatter = NumberFormat.getInstance(locale);
  50. } else if (obj instanceof Date) {
  51. // format a Date if can
  52. subFormatter = DateFormat.getDateTimeInstance(
  53. DateFormat.SHORT, DateFormat.SHORT, locale);//fix
  54. } else if (obj instanceof String) {
  55. arg = (String) obj;
  56.  
  57. } else {
  58. arg = obj.toString();
  59. if (arg == null) arg = "null";
  60. }
  61.  
  62. // At this point we are in two states, either subFormatter
  63. // is non-null indicating we should format obj using it,
  64. // or arg is non-null and we should use it as the value.
  65.  
  66. if (characterIterators != null) {
  67. // If characterIterators is non-null, it indicates we need
  68. // to get the CharacterIterator from the child formatter.
  69. if (last != result.length()) {
  70. characterIterators.add(
  71. createAttributedCharacterIterator(result.substring
  72. (last)));
  73. last = result.length();
  74. }
  75. if (subFormatter != null) {
  76. AttributedCharacterIterator subIterator =
  77. subFormatter.formatToCharacterIterator(obj);
  78.  
  79. append(result, subIterator);
  80. if (last != result.length()) {
  81. characterIterators.add(
  82. createAttributedCharacterIterator(
  83. subIterator, Field.ARGUMENT,
  84. Integer.valueOf(argumentNumber)));
  85. last = result.length();
  86. }
  87. arg = null;
  88. }
  89. if (arg != null && arg.length() > 0) {
  90. result.append(arg);
  91. characterIterators.add(
  92. createAttributedCharacterIterator(
  93. arg, Field.ARGUMENT,
  94. Integer.valueOf(argumentNumber)));
  95. last = result.length();
  96. }
  97. }
  98. else {
  99. if (subFormatter != null) {
  100. arg = subFormatter.format(obj);
  101. }
  102. last = result.length();
  103. result.append(arg);
  104. if (i == 0 && fp != null && Field.ARGUMENT.equals(
  105. fp.getFieldAttribute())) {
  106. fp.setBeginIndex(last);
  107. fp.setEndIndex(result.length());
  108. }
  109. last = result.length();
  110. }
  111. }
  112. }
  113. result.append(pattern.substring(lastOffset, pattern.length()));
  114. if (characterIterators != null && last != result.length()) {
  115. characterIterators.add(createAttributedCharacterIterator(
  116. result.substring(last)));
  117. }
  118. return result;
  119. }

Java里从来少不了字符串拼接的活,Java程序员也肯定用到过StringBuffer,StringBuilder,以及被编译器优化掉的+=。但这些都和下文要谈的无关。

直接使用"+"拼接比较多的字符串,变量一多,可读性就下降,出错的几率就增加,并且难以维护。
需要拼接的变量比较多时,可以使用MessageFormat.format。
示例:

  1. String[] tdArr={...};
  2. String result=MessageFormat.format("<tr bgcolor='#cef'><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td></tr>", tdArr);

这段代码将把数组tdArr中的四个元素分别插入到{0},{1},{2},{3}的位置。

你看看,是不是这样形式和内容有效的分开了。容易想象,当元素增多时,这种方式优势很明显。
一件事有很多手段来达成,知道那种手段更好,是你经验的体现和专业化的特征。

使用下标来决定拼接的位置,第一个参数的下标为0,pattern中下标的位置是不要求是顺序的

  1. public static void main(String[] args) {
  2. String longitude = "1.0";
  3. String latitude = "2.0";
  4. String result = "result";
  5. String geoCode = "geoCode";
  6.  
  7. String format1 = MessageFormat.format("longitude:{0},latitude:{1}, body:{2},reGeoCode:{3}", longitude, latitude, result, geoCode);
  8. System.out.println(format1);
  9. String format2 = MessageFormat.format("longitude:{3},latitude:{2}, body:{1},reGeoCode:{0}", longitude, latitude, result, geoCode);
  10. System.out.println(format2);
  11.  
  12. String format3 = MessageFormat.format("longitude:{2},latitude:{3}, body:{0},reGeoCode:{1}", longitude, latitude, result, geoCode);
  13. System.out.println(format3);
  14.  
  15. }

输出:

  1. longitude:1.0,latitude:2.0, body:result,reGeoCode:geoCode
  2. longitude:geoCode,latitude:result, body:2.0,reGeoCode:1.0
  3. longitude:result,latitude:geoCode, body:1.0,reGeoCode:2.0

java.text.MessageFormat格式化字符串时的小技巧

  1. public static void main(String[] args) throws InterruptedException {
  2. MessageFormat form = new MessageFormat(
  3. "{2,date,yyyy-MM-dd HH:mm:ss.SSS} The disk \"{1}\" contains {0,number,#.##} file(s).{3}");
  4. int fileCount = 1273273237;
  5. String diskName = "MyDisk";
  6. Object[] testArgs = {new Long(fileCount), diskName, new Date(),new Date()};
  7. System.out.println(form.format(testArgs));
  8. }
  1. 执行结果:
  2.  
  3. 2016-05-26 13:41:59.162 The disk "MyDisk" contains 1273273237 file(s).16-5-26 下午1:41

如果缺少ArgumentIndex 则会报错:

  1. java.lang.IllegalArgumentException: can't parse argument number:
  2. at java.text.MessageFormat.makeFormat(MessageFormat.java:1429)
  3. at java.text.MessageFormat.applyPattern(MessageFormat.java:479)
  4. at java.text.MessageFormat.<init>(MessageFormat.java:362)
  5. at java.text.MessageFormat.format(MessageFormat.java:840)

java.text.MessageFormat 专题的更多相关文章

  1. java.text.MessageFormat格式化字符串时的小技巧

    java.text.MessageFormat格式化字符串时的小技巧 public static void main(String[] args) throws InterruptedExceptio ...

  2. 关于java中MessageFormat.format中单引号问题

    我们知道java中可以用MessageFormat.format来格式化字符串.这个方法在我们的实际开发中经常用到,有点类似模板,这样我们就不需要用很恶心的拼接字符串了.如下面 String s1=& ...

  3. [Java]用 MessageFormat 拼接组合字符串

    package com.hy; import java.text.MessageFormat; public class Test3 { public static void main(String[ ...

  4. 由Double类型数据到数据的格式化包java.text

    需求:Double类型数据截取操作保留两位小数 解决方案: java.text.DecimalFormat df =new java.text.DecimalFormat("#.00&quo ...

  5. java.text包

    JDK在java.text包中,提供了对显示对象格式化的接口.类及异常处理,这里我们只来谈一谈text包中的format类及其子类.其中,最重要的是两个差不多互为“逆运算”的方法format(将某对象 ...

  6. java.text.NumberFormat使用方法

    NumberFormat 是全部数值格式的抽象基类. 该类提供了格式化和分析数值的接口. NumberFormat 也提供了确定 哪个语言环境具有数值格式以及它们名字的方法. package com. ...

  7. 【java】Date与String之间的转换及Calendar类:java.text.SimpleDateFormat、public Date parse(String source) throws ParseException和public final String format(Date date)

    package 日期日历类; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util. ...

  8. java.text.ParseException: Unparseable date: "2015-06-09 hh:56:19"

    1.错误描述 [DEBUG:]2015-06-09 16:56:19,520 [-------------------transcation start!--------------] java.te ...

  9. java.text.DateFormat 多线程并发问题

    在日常开发中,java.text.DateFormat 应该算是使用频率比较高的一个工具类,经常会使用它 将 Date 对象转换成字符串日期,或者将字符串日期转化成 Date 对象.先来看一段眼熟的代 ...

随机推荐

  1. 如何让eclipse输出结果的console栏自动换行?

    在console栏内容上面,鼠标右键有个word-wrap,就行了

  2. [Vue] Use Vue.js Watchers to Respond to Async Updates

    Use watchers to keep an eye on your data. Watchers are methods that are invoked when the specified a ...

  3. [Angular] Create a custom pipe

    For example we want to create a pipe, to tranform byte to Mb. We using it in html like: <div> ...

  4. QT类库与Delphi VCL类库的体系结构对比——两者十分类似!

    今天在看QT对象内存管理的一篇文章时:http://blog.csdn.net/dbzhang800/article/details/6300025想到了一个问题:就是QT类库体系结构与Delphi类 ...

  5. NOIP2015 运输计划 - 二分 + 树链剖分 / (倍增 + 差分)

    BZOJ CodeVS Uoj 题目大意: 给一个n个点的边带权树,给定m条链,你可以选择树中的任意一条边,将它置为0,使得最长的链长最短. 题目分析: 最小化最大值,二分. 二分最短长度mid,将图 ...

  6. NOIP模拟 - 树

    题目描述 给出一张n个点,m条边的无向图,摧毁每条边都需要一定的体力,并且花费的体力值各不相同,给定图中两个点x,y(x≠y),每当(x,y)之间存在路径,就需要不断摧毁当前图中花费体力最少的一条边, ...

  7. hibernate annotation 相关主键生成策略

    Hibernate 默认的全面支持 13 物种生成策略 : 1. increment 2.  identity 3. sequence 4. hilo 5. seqhilo 6. uuid 7. uu ...

  8. Hexo里如何添加广告

    前期先用Hexo做个人网站,模板可以用https://github.com/828768/maupassant-hexo,关于如何加入广告,可以看一下https://sobaigu.com/hexo- ...

  9. 五笔字根--good

    https://gss0.baidu.com/94o3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/4b90f603738da977b1b5ce57b251f8198 ...

  10. WPF 渲染原理

    原文:WPF 渲染原理 在 WPF 最主要的就是渲染,因为 WPF 是一个界面框架.想用一篇博客就能告诉大家完整的 WPF 渲染原理是不可能的.本文告诉大家 WPF 从开发者告诉如何画图像到在屏幕显示 ...