Java中的Sprintf等价物
Printf是在1.5版本中添加到Java的,但我似乎找不到如何将输出发送到字符串而不是文件(这是sprintf在C中所做的)。有人知道怎么做吗Java中的Sprintf等价物,java,string,formatting,Java,String,Formatting,Printf是在1.5版本中添加到Java的,但我似乎找不到如何将输出发送到字符串而不是文件(这是sprintf在C中所做的)。有人知道怎么做吗 // Store the formatted string in 'result' String result = String.format("%4d", i * j); // Write the result to standard output System.out.println( result ); 请参阅及其字符串是不可变的类型。您不能
// Store the formatted string in 'result'
String result = String.format("%4d", i * j);
// Write the result to standard output
System.out.println( result );
请参阅及其字符串是不可变的类型。您不能修改它们,只能返回新的字符串实例 因此,使用实例方法进行格式化没有什么意义,因为必须像以下那样调用它:
String formatted = "%s: %s".format(key, value);
最初的Java作者(和.NET作者)认为,在这种情况下,静态方法更有意义,因为您不是在修改目标,而是在调用format方法并传递输入字符串
下面是一个示例,说明了为什么format()
作为实例方法是愚蠢的。在.NET中(可能在Java中),Replace()
是一种实例方法
您可以这样做:
"I Like Wine".Replace("Wine","Beer");
但是,什么也不会发生,因为字符串是不可变的Replace()
尝试返回一个新字符串,但未将其赋值
这会导致许多常见的新手错误,如:
inputText.Replace(" ", "%20");
同样,什么也不会发生,相反,您必须:
inputText = inputText.Replace(" ","%20");
现在,如果您理解字符串是不可变的,那么这就非常有意义了。如果你不这样做,那么你只是感到困惑。Replace()
的正确位置应该是format()
所在的位置,作为String
的静态方法:
inputText = String.Replace(inputText, " ", "%20");
现在毫无疑问发生了什么事
真正的问题是,为什么这些框架的作者决定一个是实例方法,另一个是静态的?在我看来,这两种方法都更优雅地表示为静态方法
不管您的观点如何,事实是您使用静态版本不太容易出错,代码也更容易理解(没有隐藏的陷阱)
当然,有些方法作为实例方法是完美的,以String.Length()为例
在这种情况下,很明显我们并没有试图修改“123”,我们只是检查它,并返回它的长度。这是实例方法的完美候选
我对不可变对象上的实例方法的简单规则:
- 如果需要返回相同类型的新实例,请使用静态方法
- 否则,请使用实例方法
- 使用
,最接近format()
:sprintf()
- 使用
,速度稍快,但非常有限:replace(char oldchar,char newchar)
... ret += "ABCD". replace('A', HexChars.charAt((int) ((v >> 12) & 0x0f))). replace('B', HexChars.charAt((int) ((v >> 8) & 0x0f))). replace('C', HexChars.charAt((int) ((v >> 4) & 0x0f))). replace('D', HexChars.charAt((int) ( v & 0x0f))); ...
- 第三种解决方案是将字符逐个添加到
(字符是相互添加的数字!),例如:ret
... ret += HexChars.charAt((int) ((v >> 12) & 0x0f))); ret += HexChars.charAt((int) ((v >> 8) & 0x0f))); ...
…但那真的很难看。你可以对任何输出流进行printf。 不知何故,打印到字符串流中:
PrintStream ps = new PrintStream(baos);
ps.printf("there is a %s from %d %s", "hello", 3, "friends");
System.out.println(baos.toString());
这将输出以下文本来自3个朋友的问候
字符串流可以通过以下方式创建:ByteArrayOutputStream:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
您可以累积多种格式:
PrintStream ps = new PrintStream(baos);
ps.printf("there is a %s from %d %s ", "hello", 3, "friends");
ps.printf("there are %d % from a %", 2, "kisses", "girl");
System.out.println(baos.toString());
这输出有3个朋友的问候有2个女孩的亲吻调用ByteArrayOutputStream上的reset以生成干净的新字符串
ps.printf("there is a %s from %d %s", "flip", 5, "haters");
baos.reset(); //need reset to write new string
ps.printf("there are %d % from a %", 2, "kisses", "girl");
System.out.println(baos.toString());
输出将是有两个女孩的吻自从Java 13以来,您在字符串上设置了
格式的
方法,该方法与文本块一起作为预览功能添加。
您可以使用它代替String.format()
Assertions.assertEquals(
“%s%d%.3f”。格式化(“foo”,123,7.89),
“foo 123 7.890”
);
我看到您不知怎么地想到了我建议修改格式字符串的想法。我从来没有考虑过有人会期望字符串发生变化的可能性,因为它们的不变性是非常基本的。由于格式字符串通常更像“价格是%4d”,而不是“%4d”,我仍然认为有很多可能引起混淆。您对静态方法有什么看法?:)这个答案似乎与这个问题无关。答案甚至不是Java,似乎与.NET-1更相关。降票b/c,这是切向的。不一定是不可变的最佳样式。这种风格比简单的方法调用更冗长,尤其是对于链式操作。它放弃了运行时多态性,因为它调用了静态方法,这很重要。所有这些都是好主意,但是把你的代码变成了你的同事无法理解的只写代码。
PrintStream ps = new PrintStream(baos);
ps.printf("there is a %s from %d %s ", "hello", 3, "friends");
ps.printf("there are %d % from a %", 2, "kisses", "girl");
System.out.println(baos.toString());
ps.printf("there is a %s from %d %s", "flip", 5, "haters");
baos.reset(); //need reset to write new string
ps.printf("there are %d % from a %", 2, "kisses", "girl");
System.out.println(baos.toString());