java小知识之String.format中的%秘密
String.format是Java中String类非常常用的一个方法,可以帮我们将占位符替换成变量,比如%d
可以作为整型的占位符,%s
可以作为字符串的占位符,但是吧有的时候常用归常用,有的时候碰到问题了还是得学习记录下
比如我们要写一个字符串替换方法1
2
3
4
5public class Demo {
public static void main(String[] args) {
System.out.printf("成功是%d%的努力和%d%的天赋", 99, 1);
}
}
就是希望输出 “成功是99%的努力和1%的天赋” ,先不管这句话的正确性,看看能不能正常输出(肯定是不能)1
2
3
4
5
6
7Exception in thread "main" java.util.UnknownFormatConversionException: Conversion = '的'
at java.util.Formatter.checkText(Formatter.java:2579)
at java.util.Formatter.parse(Formatter.java:2555)
at java.util.Formatter.format(Formatter.java:2501)
at java.io.PrintStream.format(PrintStream.java:970)
at java.io.PrintStream.printf(PrintStream.java:871)
at demo.Demo.main(Demo.java:9)
会有这样的报错,虽然是个小问题我们还是来仔细研究下,
首先这边format函数会根据可能的占位符去提取并分割字符串1
2
3
4
5
6
7
8
9
10
11private static final String formatSpecifier
= "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])";
private static Pattern fsPattern = Pattern.compile(formatSpecifier);
/**
* Finds format specifiers in the format string.
*/
private FormatString[] parse(String s) {
ArrayList<FormatString> al = new ArrayList<>();
Matcher m = fsPattern.matcher(s);
比如上面的字符串,可以提取到两个有效的 %d
然后对剩余的进行分割,分割后再遍历校验每一个字符
如果碰到单独的 %
就说明出现了错误的分隔符
会调用 checkText
来识别报错
而如果我们想要能够正常输出%
也非常简单,只需要使用两个百分号 %%
这里其实就是匹配到了上面 formatSpecifier
的最后面,%
后面可以匹配的可以使 a-z
和 A-Z
以及 %
当是连续的两个 %%
时就会被识别成转义成实际的 %
1
2
3public static void main(String[] args) {
System.out.printf("成功是%d%%的努力和%d%%的天赋", 99, 1);
}
换成这样就能正常输出了