Java 字符串格式化详解

作者: 牙锅子 | 来源:发表于2016-10-20 10:45 被阅读1214次

    版权声明:本文为博主原创文章,未经博主允许不得转载。
    微博:厉圣杰
    文中如有纰漏,欢迎大家留言指出。

    在 Java 的 String 类中,可以使用 format() 方法格式化字符串,该方法有两种重载形式: String.format(String format, Object... args)String.format(Locale locale, String format, Object... args)。两者的唯一区别是前者使用本地语言环境,后者使用指定语言环境
    查看源码可以发现,该方法最终调用 java.util.Formatter 类的 format 方法。

    public static String format(String format, Object... args) {
       return new Formatter().format(format, args).toString();
    }
    
    public static String format(Locale l, String format, Object... args) {
       return new Formatter(l).format(format, args).toString();
    }
    

    所以,掌握了 Formatter 的使用,也就掌握了 String.format 的使用,从此 Java 中格式化字符串再无敌手~ 所以我们这里先来讲解 Formatter 的用法。

    参考 Java Api 中关于 Formatter 的使用说明,我们可以发现 format 方法的第一个参数是有固定格式的。其格式如下:

    %[argument_index$][flags][width][.precision]conversion
    
    argument_index: 可选,是一个十进制整数,用于表明参数在参数列表中的位置。第一个参数由 "1$" 引用,第二个参数由 "2$" 引用,依此类推。
    
    flags: 可选,用来控制输出格式
    
    width: 可选,是一个正整数,表示输出的最小长度
    
    precision:可选,用来限定输出的精度
    
    conversion:必须,用来表示如何格式化参数的字符
    

    参考文档,可以发现 Java 其实把格式化划分为两大类:常规类型格式化和时间日期格式化,下面我们就先来介绍一下常规类型的格式化。

    补充:Java 中对格式化其实还有根据类型来分类的,但这里为了方便讲述,只简单的依据格式化的参数类型来讲述,如果以后有机会,会开一篇更详细的博客。

    常规类型格式化

    在开始之前,这里先放一段 Api 中提供的示例代码,你可以带着示例中的问题去看接下来的内容,也可以看完之后回来看示例,你看懂了多少呢?

    StringBuilder sb = new StringBuilder();
    // Send all output to the Appendable object sb
    Formatter formatter = new Formatter(sb, Locale.US);
    
    // Explicit argument indices may be used to re-order output.
    formatter.format("%4$2s %3$2s %2$2s %1$2s", "a", "b", "c", "d")
    // -> " d  c  b  a"
    
    // Optional locale as the first argument can be used to get
    // locale-specific formatting of numbers.  The precision and width can be
    // given to round and align the value.
    formatter.format(Locale.FRANCE, "e = %+10.4f", Math.E);
    // -> "e =    +2,7183"
    
    // The '(' numeric flag may be used to format negative numbers with
    // parentheses rather than a minus sign.  Group separators are
    // automatically inserted.
    formatter.format("Amount gained or lost since last statement: $ %(,.2f",
                   balanceDelta);
    // -> "Amount gained or lost since last statement: $ (6,217.58)"
    
    // Writes a formatted string to System.out.
    System.out.format("Local time: %tT", Calendar.getInstance());
    // -> "Local time: 13:34:18"
    
    // Writes formatted output to System.err.
    System.err.printf("Unable to open file '%1$s': %2$s",
                    fileName, exception.getMessage());
    // -> "Unable to open file 'food': No such file or directory"
    
    Calendar c = new GregorianCalendar(1995, MAY, 23);
    String s = String.format("Duke's Birthday: %1$tb %1$te, %1$tY", c);
    // -> s == "Duke's Birthday: May 23, 1995"
    

    conversion

    从上述内容可以发现,只有 conversion 这个参数是必选的。 conversion 是用来表示如何格式化参数的字符。先来看个例子:

    //输出:我的名字叫:小明
    System.out.println(String.format("大家好,我叫:%s","小明"));
    

    %s 是一个占位符,s 是一个转换符,指明将参数格式化为字符串。值得注意的是,占位符代表的格式化类型必须与参数的类型相兼容,否则运行时会抛出异常,如:

    System.out.println(String.format("大家好,我叫:%d","小明"));
    

    运行这段代码,就会抛出如下异常:

    Exception in thread "main" java.util.IllegalFormatConversionException: d != java.lang.String
       at java.util.Formatter$FormatSpecifier.failConversion(Formatter.java:4302)
       at java.util.Formatter$FormatSpecifier.printInteger(Formatter.java:2793)
       at java.util.Formatter$FormatSpecifier.print(Formatter.java:2747)
       at java.util.Formatter.format(Formatter.java:2520)
       at java.util.Formatter.format(Formatter.java:2455)
       at java.lang.String.format(String.java:2940)
    

    那么,转换符除了 s ,还有哪些呢?那我们就来看下代码:

    /**
    * conversion 的具体占位符
    */
    private static void formatConversion() {
      System.out.println(String.format("'b':将参数格式化为boolean类型输出,`B`的效果相同,但结果中字母为大写。%b", false));
      System.out.println(String.format("'h':将参数格式化为散列输出,原理:Integer.toHexString(arg.hashCode()),`H`的效果相同,但结果中字母为大写。%h", "ABC"));
      System.out.println(String.format("'s':将参数格式化为字符串输出,如果参数实现了 Formattable接口,则调用 formatTo方法。`S`的效果相同。%s", 16));
      System.out.println(String.format("FormatImpl类实现了Formattable接口:%s", new FormatImpl()));
      System.out.println(String.format("'c':将参数格式化为Unicode字符,'C'的效果相同。%c", 'A'));
      System.out.println(String.format("'d':将参数格式化为十进制整数。%d", 11));
      System.out.println(String.format("'o':将参数格式化为八进制整数。%o", 9));
      System.out.println(String.format("'x':将参数格式化为十六进制整数。%x", 17));
      System.out.println(String.format("'e':将参数格式化为科学计数法的浮点数,'E'的效果相同。%E", 10.000001));
      System.out.println(String.format("'f':将参数格式化为十进制浮点数。%f", 10.000001));
      System.out.println(String.format("'g':根据具体情况,自动选择用普通表示方式还是科学计数法方式,'G'效果相同。10.01=%g", 10.01));
      System.out.println(String.format("'g':根据具体情况,自动选择用普通表示方式还是科学计数法方式,'G'效果相同。10.00000000005=%g", 10.00000000005));
      System.out.println(String.format("'a':结果被格式化为带有效位数和指数的十六进制浮点数,'A'效果相同,但结果中字母为大写。%a", 10.1));
      System.out.println(String.format("'t':时间日期格式化前缀,会在后面讲述"));
      System.out.println(String.format("'%%':输出%%。%%"));
      System.out.println(String.format("'n'平台独立的行分隔符。System.getProperty(\"line.separator\")可以取得平台独立的行分隔符,但是用在format中间未免显得过于烦琐了%n已经换行"));
    }
       
    private static class FormatImpl implements Formattable {
       
      @Override
      public void formatTo(Formatter formatter, int flags, int width, int precision) {
          formatter.format("我是Formattable接口的实现类");
      }
    }
    

    输出如下:

    'b':将参数格式化为boolean类型输出,`B`的效果相同,但结果中字母为大写。false
    'h':将参数格式化为散列输出,原理:Integer.toHexString(arg.hashCode()),`H`的效果相同,但结果中字母为大写。fc42
    's':将参数格式化为字符串输出,如果参数实现了 Formattable接口,则调用 formatTo方法。`S`的效果相同。16
    FormatImpl类实现了Formattable接口:我是Formattable接口的实现类
    'c':将参数格式化为Unicode字符,'C'的效果相同。A
    'd':将参数格式化为十进制整数。11
    'o':将参数格式化为八进制整数。11
    'x':将参数格式化为十六进制整数。11
    'e':将参数格式化为科学计数法的浮点数,'E'的效果相同。1.000000E+01
    'f':将参数格式化为十进制浮点数。10.000001
    'g':根据具体情况,自动选择用普通表示方式还是科学计数法方式,'G'效果相同。10.01=10.0100
    'g':根据具体情况,自动选择用普通表示方式还是科学计数法方式,'G'效果相同。10.00000000005=10.0000
    'a':结果被格式化为带有效位数和指数的十六进制浮点数,'A'效果相同,但结果中字母为大写。0x1.4333333333333p3
    't':时间日期格式化前缀,会在后面讲述
    '%':输出%。%
    'n':平台独立的行分隔符。System.getProperty("line.separator")可以取得平台独立的行分隔符,但是用在format中间未免显得过于烦琐了
    已经换行
    

    补充

    • 对于浮点转换符 'e' 、'E' 和 'f',精度是小数点分隔符后的位数。如果转换符是 'g' 或 'G',那么精度是舍入计算后所得数值的所有位数。如果转换是 'a' 或 'A',则不必指定精度。
    • 对于部分转换符,如 'b' 和 'B' ,两者转换效果是相似的,但是 'B' 会把输出中的字母都转换为大写,其它相似特性的转换符应该还有好多,大家可以去找一下O(∩_∩)O哈哈~

    argument_index

    还记得前面那个小明的例子嘛?现在我们来改变一下输出,要求输出如下内容:

    //其中,小明、25、小小明都是由参数传递
    大家好,我叫:小明,今年:25岁。小明是小小明的爸爸。
    

    看到这个,大家会怎么做呢?也许,你会写成:

    System.out.println(String.format("大家好,我叫:%s,今年:%d岁。%s是%s的爸爸。", "小明", 25, "小明", "小小明"));
    

    恩,这样做输出的确没错,但是我们却重复输入参数“小明”。这里,就要用到 argument_index 这个参数。使用 argument_index 可以指定使用第几个参数来替换占位符,一旦使用 argument_index 用于指出参数在参数列表中位置,则所有占位符都要加上,否则会出错。修改之后的代码如下:

    System.out.println(String.format("大家好,我叫:%1$s,今年:%2$d岁。%1$s是%3$s的爸爸。", "小明", 25, "小小明"));
    

    补充:对于

    System.out.println(String.format("大家好,我叫:%s,今年:%d岁。%s是%s的爸爸。", "小明", 25, "小明", "小小明"));
    

    在 Java 中执行可能没什么问题,但如果把 "大家好,我叫:%s,今年:%d岁。%s是%s的爸爸。" 放到 Android 的 strings.xml 中,则会出现错误,解决办法就是指明每个参数在参数列表中位置。

    flags

    flags是可选参数,用于控制输出的格式,比如左对齐、金额用逗号隔开。

    '-' 在最小宽度内左对齐,不可以与“用0填充”同时使用
    
    '+' 结果总是包括一个符号
    
    ' ' 正值前加空格,负值前加负号
    
    '0' 结果将用零来填充
    
    ',' 每3位数字之间用“,”分隔(只适用于fgG的转换)
    
    '(' 若参数是负数,则结果中不添加负号而是用圆括号把数字括起来(只适用于eEfgG的转换)
    
    /**
    * flags 的标识
    */
    private static void formatFlags() {
       System.out.println("'-':在最小宽度内左对齐,不可与\"用0填充\"同时使用。");
       System.out.println(String.format("设置最小宽度为8为,左对齐。%-8d:%-8d:%-8d%n", 1, 22, 99999999));
       System.out.println(String.format("'0':结果将用零来填充。设置最小宽度为8,%08d:%08d:%08d", 1, -22, 99999990));
       System.out.println(String.format("'+':结果总是包括一个符号。%+d:%+d:%+d", 1, -2, 0));
       System.out.println(String.format("' ':正值前加空格,负值前加负号。% d:% d:% d", 1, -2, 0));
       System.out.println(String.format("',':每3位数字之间用“,”分隔(只适用于fgG的转换)。%,d:%,d:%,d", 1, 100, 1000));
       System.out.println(String.format("'(':若参数是负数,则结果中不添加负号而是用圆括号把数字括起来(只适用于eEfgG的转换)。%(d:%(d", 1, -1));
    }
    

    输出如下:

    '-':在最小宽度内左对齐,不可与"用0填充"同时使用。
    设置最小宽度为8为,左对齐。1       :22      :99999999
    
    '0':结果将用零来填充。设置最小宽度为8,00000001:-0000022:99999990
    '+':结果总是包括一个符号。+1:-2:+0
    ' ':正值前加空格,负值前加负号。 1:-2: 0
    ',':每3位数字之间用“,”分隔(只适用于fgG的转换)。1:100:1,000
    '(':若参数是负数,则结果中不添加负号而是用圆括号把数字括起来(只适用于eEfgG的转换)。1:(1)
    

    width

    width是可选参数,用于控制输出的宽度。示例如下:

    System.out.println(String.format("设置最小宽度为8,不满8位用0填充:%08d:%08d", 1, -10000000));
    

    输出如下:

    设置最小宽度为8,不满8位用0填充:00000001:-10000000
    

    但是 width 的值不能为 0 ,否则会抛出

    Exception in thread "main" java.util.DuplicateFormatFlagsException: Flags = '0'
        at java.util.Formatter$Flags.parse(Formatter.java:4443)
        at java.util.Formatter$FormatSpecifier.flags(Formatter.java:2640)
        at java.util.Formatter$FormatSpecifier.<init>(Formatter.java:2709)
        at java.util.Formatter.parse(Formatter.java:2560)
        at java.util.Formatter.format(Formatter.java:2501)
        at java.util.Formatter.format(Formatter.java:2455)
        at java.lang.String.format(String.java:2940)
    

    precision

    precision是可选参数,用来限定输出的精度,用于浮点数。示例如下:

    /**
    * 格式化精度,仅限浮点数
    */
    private static void formatPrecision() {
       //System.out.println(String.format("设置精度为2位:%.2d", 1));
       System.out.println(String.format("设置精度为2位:%.2f", 1f));
    }
    

    输出如下:

    设置精度为2位:1.00
    

    值得注意的是,如果对整型数据设置精度,则会抛出如下异常:

    Exception in thread "main" java.util.IllegalFormatPrecisionException: 2
        at java.util.Formatter$FormatSpecifier.checkInteger(Formatter.java:2984)
        at java.util.Formatter$FormatSpecifier.<init>(Formatter.java:2729)
        at java.util.Formatter.parse(Formatter.java:2560)
        at java.util.Formatter.format(Formatter.java:2501)
        at java.util.Formatter.format(Formatter.java:2455)
        at java.lang.String.format(String.java:2940)
    

    时间日期格式化

    在平时开发中,经常会碰到要显示时间日期的。以前写过一篇 Android 时间、日期相关类和方法 的博客,里面对 Android 中经常出现的时间日期格式做了总结,但觉得还是过于繁琐,这次总结 Java 中格式化输出,没想到 Java 中已经包含了如此多关于时间的转换符,完全能应对日常开发需要,而且不用复杂的计算。

    Java 中时间日期格式化的转换符可以分为三类,分别是:时间格式化转换符、日期格式化转换符、时间日期格式化转换符。相比于日期和时间日期格式化转换符,时间格式化转换符就相对多一点。

    时间日期格式化字符串的格式如下:

    %[argument_index$][flags][width]conversion
    

    相对于普通的格式,时间日期格式化少了 precision ,而 conversion 是由两个字符组成,且第一个字符固定为 tT

    网上部分博文是贴了转换符说明的表格,但是写完代码之后突然发现,Java 格式化输出这部分内容,看代码和输出其实比看表格更直观,谁让我们是程序员呢?下面就用代码来讲述一下时间日期格式化转换符的三种类别。

    格式化时间

    示例代码如下:

    /**
    * 格式化时间
    */
    private static void formatTime() {
       System.out.println("这是格式化时间相关的,具体输出跟你执行代码时间有关");
       Calendar calendar = Calendar.getInstance();
       System.out.println(String.format("'H':2位数24小时制,不足两位前面补0:%tH(范围:00-23)", calendar));
       System.out.println(String.format("'I':2位数12小时制,不足两位前面补0:%tI(范围:01-12)", calendar));
       System.out.println(String.format("'k':24小时制,不足两位不补0:%tk(范围:0-23)", calendar));
       System.out.println(String.format("'l':12小时制,不足两位不补0:%tl(范围:1-12)", calendar));
       System.out.println(String.format("'M':2位数的分钟,不足两位前面补0:%tM(范围:00-59)", calendar));
       System.out.println(String.format("'S':分钟中的秒,2位数,不足两位前面补0,60是支持闰秒的一个特殊值:%tS(范围:00-60)", calendar));
       System.out.println(String.format("'L':3位数的毫秒,不足三位前面补0:%tL(范围:000-999)", calendar));
       System.out.println(String.format("'N':9位数的微秒,不足九位前面补0:%tN(范围:000000000-999999999)", calendar));
    
       System.out.println(String.format("'p':输出本地化的上午下午,例如,Locale.US为am或pm,Locale.CHINA为上午或下午", calendar));
       System.out.println(String.format(Locale.US, "Local.US=%tp", calendar));
       System.out.println(String.format(Locale.CHINA, "Local.CHINA=%tp", calendar));
       System.out.println();
    
       System.out.println(String.format("'z':时区:%tz", calendar));
       System.out.println(String.format("'Z':时区缩写字符串:%tZ", calendar));
       System.out.println(String.format("'s':从1970-1-1 00:00到现在所经历的秒数:%ts", calendar));
       System.out.println(String.format("'Q':从1970-1-1 00:00到现在所经历的豪秒数:%tQ", calendar));
    }
    

    输出结果如下:

    这是格式化时间相关的,具体输出跟你执行代码时间有关
    'H':2位数24小时制,不足两位前面补0:21(范围:00-23)
    'I':2位数12小时制,不足两位前面补0:09(范围:01-12)
    'k':24小时制,不足两位不补0:21(范围:0-23)
    'l':12小时制,不足两位不补0:9(范围:1-12)
    'M':2位数的分钟,不足两位前面补0:26(范围:00-59)
    'S':分钟中的秒,2位数,不足两位前面补0,60是支持闰秒的一个特殊值:44(范围:00-60)
    'L':3位数的毫秒,不足三位前面补0:502(范围:000-999)
    'N':9位数的微秒,不足九位前面补0:502000000(范围:000000000-999999999)
    'p':输出本地化的上午下午,例如,Locale.US为am或pm,Locale.CHINA为上午或下午
    Local.US=pm
    Local.CHINA=下午
    
    'z':时区:+0800
    'Z':时区缩写字符串:CST
    's':从1970-1-1 00:00到现在所经历的秒数:1476883604
    'Q':从1970-1-1 00:00到现在所经历的豪秒数:1476883604502
    

    格式化日期

    示例代码如下:

    /**
     * 格式化日期
     */
    private static void formatDate() {
        System.out.println("-----------------------我是微笑的分割线O(∩_∩)O哈哈~-----------------------------");
        System.out.println("这是格式化时间相关的,具体输出跟你执行代码时间有关");
        Calendar calendar = Calendar.getInstance();
        System.out.println(String.format("'B':本地化显示月份字符串,如:January、February"));
        System.out.println(String.format("'b':本地化显示月份字符串的缩写,如:Jan、Feb"));
        System.out.println(String.format("'h':本地化显示月份字符串的缩写,效果同'b'"));
        System.out.println(String.format(Locale.US, "Locale.US 月份=%1$tB,缩写=%1$tb", calendar));
        System.out.println(String.format(Locale.CHINA, "Locale.CHINA 月份=%1$tB,缩写=%1$tb", calendar));
    
        System.out.println(String.format("'A':本地化显示星期几字符串,如:Sunday、Monday"));
        System.out.println(String.format("'a':本地化显示星期几字符串的缩写,如:Sun、Mon"));
        System.out.println(String.format(Locale.US, "Locale.US 星期几=%1$tA,缩写=%1$ta", calendar));
        System.out.println(String.format(Locale.CHINA, "Locale.CHINA 星期几=%1$tA,缩写=%1$ta", calendar));
    
        System.out.println(String.format("'C':年份除以100的结果,显示两位数,不足两位前面补0:%tC(范围:00-99)", calendar));
        System.out.println(String.format("'Y':显示四位数的年份,格利高里历,即公历。不足四位前面补0:%tY", calendar));
        System.out.println(String.format("'y':显示年份的后两位:%ty(范围:00-99)", calendar));
        System.out.println(String.format("'j':显示当前公历年的天数:第%tj天(范围:001-366)", calendar));
        System.out.println(String.format("'m':显示当前月份:%tm月(范围:01-13?怎么会有13个月?)", calendar));
        System.out.println(String.format("'d':显示是当前月的第几天,不足两位前面补0:%1$tm月第%1$td天(范围:01-31)", calendar));
        System.out.println(String.format("'e':显示是当前月的第几天:%1$tm月第%1$te天(范围:1-31)", calendar));
    }
    

    输出结果如下:

    -----------------------我是微笑的分割线O(∩_∩)O哈哈~-----------------------------
    这是格式化时间相关的,具体输出跟你执行代码时间有关
    'B':本地化显示月份字符串,如:January、February
    'b':本地化显示月份字符串的缩写,如:Jan、Feb
    'h':本地化显示月份字符串的缩写,效果同'b'
    Locale.US 月份=October,缩写=Oct
    Locale.CHINA 月份=十月,缩写=十月
    'A':本地化显示星期几字符串,如:Sunday、Monday
    'a':本地化显示星期几字符串的缩写,如:Sun、Mon
    Locale.US 星期几=Wednesday,缩写=Wed
    Locale.CHINA 星期几=星期三,缩写=星期三
    'C':年份除以100的结果,显示两位数,不足两位前面补0:20(范围:00-99)
    'Y':显示四位数的年份,格利高里历,即公历。不足四位前面补0:2016
    'y':显示年份的后两位:16(范围:00-99)
    'j':显示当前公历年的天数:第293天(范围:001-366)
    'm':显示当前月份:10月(范围:01-13?怎么会有13个月?)
    'd':显示是当前月的第几天,不足两位前面补0:10月第19天(范围:01-31)
    'e':显示是当前月的第几天:10月第19天(范围:1-31)
    

    补充:在文档中发现一个略微奇怪的问题,就是 m 转换符,文档上的大意是:该转换符用于显示当前月是这一年的第几个月,文档里给的范围竟然是01-13,一年怎么会有13个月,告诉我不是我理解错了?

    格式化时间日期

    示例代码如下:

    /**
     * 格式化时间日期
     */
    private static void formatTimeAndDate() {
        System.out.println("-----------------------我是微笑的分割线O(∩_∩)O哈哈~-----------------------------");
        System.out.println("这是格式化时间相关的,具体输出跟你执行代码时间有关");
        Calendar calendar = Calendar.getInstance();
        //%tH:%tM的缩写
        System.out.println(String.format("'R':将时间格式化为:HH:MM(24小时制)。输出:%tR", calendar));
        //%tH:%tM:%tS的缩写
        System.out.println(String.format("'T':将时间格式化为:HH:MM:SS(24小时制)。输出:%tT", calendar));
        //%tI:%tM:%tS %Tp的缩写,输出形如:
        System.out.println(String.format("'r':将时间格式化为:09:23:15 下午,跟设置的语言地区有关。输出:%tr", calendar));
        //%tm/%td/%ty的缩写,输出形如
        System.out.println(String.format("'D':将时间格式化为:10/19/16。输出:%tD", calendar));
        //%tY-%tm-%td,输出形如:
        System.out.println(String.format("'F':将时间格式化为:2016-10-19。输出:%tF", calendar));
        //%ta %tb %td %tT %tZ %tY,输出形如:Sun Jul 20 16:17:00 EDT 1969
        System.out.println(String.format("'c':将时间格式化为\"Sun Jul 20 16:17:00 EDT 1969\"。输出:%tc", calendar));
    }
    

    输出结果如下:

    -----------------------我是微笑的分割线O(∩_∩)O哈哈~-----------------------------
    这是格式化时间相关的,具体输出跟你执行代码时间有关
    'R':将时间格式化为:HH:MM(24小时制)。输出:21:26
    'T':将时间格式化为:HH:MM:SS(24小时制)。输出:21:26:44
    'r':将时间格式化为:09:23:15 下午,跟设置的语言地区有关。输出:09:26:44 下午
    'D':将时间格式化为:10/19/16。输出:10/19/16
    'F':将时间格式化为:2016-10-19。输出:2016-10-19
    'c':将时间格式化为"Sun Jul 20 16:17:00 EDT 1969"。输出:星期三 十月 19 21:26:44 CST 2016
    

    总结

    系统的介绍了 Java 中格式化字符串的方式及相关的转换符。不过只是对此有印象,方便日后温习,还得在日常中不断加强使用。

    虽然 Formatter 中提供了很多关于时间日期的转换符,而且能满足日常的绝大部分使用,但还是存在限制,所以对于有特殊要求的时间格式,还是要学会自己定制。

    String.format 这个方法很实用,但如果是大批量进行字符串格式化,就需要考虑到性能方面的问题,因为每次调用 format() 方法都会 new 一个 Formatter 对象。而在 Java 中频繁创建对象需要大量时间,而且还要花时间对这些对象进行垃圾回收和处理。最好的办法就是自己把 DateFormat 、 NumberFormat 、 MessageFormat 这些类封装成静态工具。

    参考

    1. Java Api -- Formatter
    2. String.format()方法使用说明
    3. JAVA字符串格式化-String.format()的使用

    相关文章

      网友评论

        本文标题:Java 字符串格式化详解

        本文链接:https://www.haomeiwen.com/subject/ndsfuttx.html