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 );
请参阅format及其语法
字符串是不可变类型。你不能修改它们,只能返回新的字符串实例。
正因为如此,使用实例方法格式化没有什么意义,因为它必须像这样调用:
String formatted = "%s: %s".format(key, value);
最初的Java作者(和。net作者)认为静态方法在这种情况下更有意义,因为您不需要修改目标,而是调用一个格式方法并传入一个输入字符串。
下面是一个例子,说明为什么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 ()
int length = "123".Length();
在这种情况下,很明显我们并没有试图修改“123”,我们只是检查它,并返回它的长度。这是实例方法的理想候选。
我对不可变对象的实例方法的简单规则:
如果需要返回相同类型的新实例,请使用静态方法。 否则,使用实例方法。
这两种解决方案都可以模拟printf,但方式不同。 例如,要将一个值转换为十六进制字符串,你有以下两个解决方案:
with format(), closest to sprintf(): final static String HexChars = "0123456789abcdef"; public static String getHexQuad(long v) { String ret; if(v > 0xffff) ret = getHexQuad(v >> 16); else ret = ""; ret += String.format("%c%c%c%c", HexChars.charAt((int) ((v >> 12) & 0x0f)), HexChars.charAt((int) ((v >> 8) & 0x0f)), HexChars.charAt((int) ((v >> 4) & 0x0f)), HexChars.charAt((int) ( v & 0x0f))); return ret; } with replace(char oldchar , char newchar), somewhat faster but pretty limited: ... 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))); ... There is a third solution consisting of just adding the char to ret one by one (char are numbers that add to each other!) such as in: ... ret += HexChars.charAt((int) ((v >> 12) & 0x0f))); ret += HexChars.charAt((int) ((v >> 8) & 0x0f))); ...
...但那就太难看了。
你可以用PrintStream对任何输出流做printf。 就像这样,打印到字符串流中:
PrintStream ps = new PrintStream(baos);
ps.printf("there is a %s from %d %s", "hello", 3, "friends");
System.out.println(baos.toString());
这输出下面的文本有一个hello从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上的重置来生成一个干净的新字符串
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());
输出是一个女孩的2个吻
从Java 13开始,你已经格式化了String上的1个方法,它与文本块一起添加作为预览功能2。 你可以用它来代替String.format()
Assertions.assertEquals(
"%s %d %.3f".formatted("foo", 123, 7.89),
"foo 123 7.890"
);
推荐文章
- 到底是什么导致了堆栈溢出错误?
- 为什么Android工作室说“等待调试器”如果我不调试?
- 是否有可能更新一个本地化的故事板的字符串?
- 为什么字符串类型的默认值是null而不是空字符串?
- Java:路径vs文件
- 在Python中包装长行
- ExecutorService,如何等待所有任务完成
- Maven依赖Servlet 3.0 API?
- 在Windows批处理脚本中格式化日期和时间
- 如何在IntelliJ IDEA中添加目录到应用程序运行概要文件中的类路径?
- getter和setter是糟糕的设计吗?相互矛盾的建议
- Android room persistent: AppDatabase_Impl不存在
- Java的String[]在Kotlin中等价于什么?
- Intellij IDEA上的System.out.println()快捷方式
- 使用Spring RestTemplate获取JSON对象列表