Formatter 不能用在字符串上吗?

May Formatter not be used on Strings?

当我检查以下代码的结果时,我被难住了:

public class StringBuilderTester {

    public static void main(String[] args) {
        StringBuilder matrix = new StringBuilder();
        Random r = new Random();
        Formatter formatter = new Formatter();
        for (int j=0;j<10;j++) {
            String[] strings = new String[10];
            StringBuilder formatString = new StringBuilder();
            for (int i=0;i<10;i++) {
                formatString.append("%-10.5s");
                strings[i] = new Integer(r.nextInt(10)).toString();
            }
            formatString.append("\n");
            matrix.append(formatter.format(formatString.toString(), strings));  //gives me unexpected result: 1+2+3+..+10=55 lines of 10 cols of random ints
            //matrix.append(String.format(formatString.toString(), strings));  //gives me expected results: 10 lines of 10 cols of random ints
        }
        System.out.println(matrix.toString());
    }
}

我得到 55 (!) 行,每行 10 列,每行都是格式整齐的整数:第 1 行,然后是第 1 行和第 2 行,然后是第 1、2 和 3 行,依此类推。 formatter.format 似乎是渐进式的。

formatter.format 更改为 String.format 时,结果符合预期:10 行格式整齐的整数。

Java 参考指出

Strings may be formatted using the static method String.format.

但没有迹象表明 new Format().formatter(...) 可能 不会 用于字符串。 (如果我使用构造函数 Format(Appendable matrix) 一切都按预期工作。)

这种不稳定行为的解释是什么?

两种情况其实都是expected behaviourFormatter class 有一个内部缓冲区(默认为 StringBuilder),它将每次调用 format 的结果附加到其中,toString() 方法 returns缓冲区的全部内容。所以你第一次打电话

matrix.append(formatter.format(formatString.toString(), strings));

它将 row1 添加到格式化程序缓冲区,然后将其附加到矩阵。再次调用它,它将第 2 行添加到缓冲区,但现在缓冲区包含第 1 行和第 2 行,所以这两行都被添加到矩阵中,矩阵现在有第 1 行、第 1 行、第 2 行。继续进行并最终添加 55总行数。

old matrix    +    buffer    =    new matrix
                   1              1
1                  12             112
112                123            112123
112123             1234           1121231234
...and so on

另一方面,如果您只调用 String.format,它会产生与 formatter.format 相同的输出,但不会将其附加到任何缓冲区。这样,在每次循环迭代中,只有创建的最后一行被附加到矩阵,这是预期的结果。

TL;DR: formatter.format 将格式化行添加到内部缓冲区,然后输出整个缓冲区,而 String.format 只是输出格式化行。