java对于字符串拼接一般都喜欢用String.format("xx",arg)
,如下
那么这个简单实用的小功能底层是作何实现呢?
return new Formatter().format(format, args).toString();
在java.util.Formatter#format(java.util.Locale, java.lang.String, java.lang.Object...)
第2493行方法如下:
public Formatter format(Locale l, String format, Object ... args) {
ensureOpen();
// index of last argument referenced
int last = -1;
// last ordinary index
int lasto = -1;
FormatString[] fsa = parse(format);
for (int i = 0; i < fsa.length; i++) {
FormatString fs = fsa[i];
int index = fs.index();
try {
switch (index) {
case -2: // fixed string, "%n", or "%%"
fs.print(null, l);
break;
case -1: // relative index
if (last < 0 || (args != null && last > args.length - 1))
throw new MissingFormatArgumentException(fs.toString());
fs.print((args == null ? null : args[last]), l);
break;
case 0: // ordinary index
lasto++;
last = lasto;
if (args != null && lasto > args.length - 1)
throw new MissingFormatArgumentException(fs.toString());
fs.print((args == null ? null : args[lasto]), l);
break;
default: // explicit index
last = index - 1;
if (args != null && last > args.length - 1)
throw new MissingFormatArgumentException(fs.toString());
fs.print((args == null ? null : args[last]), l);
break;
}
} catch (IOException x) {
lastException = x;
}
}
return this;
}
其中第九行的FormatString[] fsa = parse(format);
将字符串按照制定规则拆分成多个,如上诉例子,将返回
java.util.Formatter#parse
跟进代码如下:private FormatString[] parse(String s) {
ArrayList<FormatString> al = new ArrayList<>();
Matcher m = fsPattern.matcher(s);
for (int i = 0, len = s.length(); i < len; ) {
if (m.find(i)) {
// Anything between the start of the string and the beginning
// of the format specifier is either fixed text or contains
// an invalid format string.
if (m.start() != i) {
// Make sure we didn‘t miss any invalid format specifiers
checkText(s, i, m.start());
// Assume previous characters were fixed text
al.add(new FixedString(s.substring(i, m.start())));
}
al.add(new FormatSpecifier(m));
i = m.end();
} else {
// No more valid format specifiers. Check for possible invalid
// format specifiers.
checkText(s, i, len);
// The rest of the string is fixed text
al.add(new FixedString(s.substring(i)));
break;
}
}
return al.toArray(new FormatString[al.size()]);
}
通过第三行,显然是通过正则表达式拆分的,java.util.Formatter#parse的2537行看到正则表达式为:
"%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])";
具体逻辑如下
我的名字:%s,年龄:%d","张三
,初始状态i为0,指向字符‘我‘
我的名字:
%s
把下标为i以后的所有字串都添加进来
for (int i = 0; i < fsa.length; i++) {
FormatString fs = fsa[i];
int index = fs.index();
try {
switch (index) {
case -2: // fixed string, "%n", or "%%"
fs.print(null, l);
break;
case -1: // relative index
if (last < 0 || (args != null && last > args.length - 1))
throw new MissingFormatArgumentException(fs.toString());
fs.print((args == null ? null : args[last]), l);
break;
case 0: // ordinary index
lasto++;
last = lasto;
if (args != null && lasto > args.length - 1)
throw new MissingFormatArgumentException(fs.toString());
fs.print((args == null ? null : args[lasto]), l);
break;
default: // explicit index
last = index - 1;
if (args != null && last > args.length - 1)
throw new MissingFormatArgumentException(fs.toString());
fs.print((args == null ? null : args[last]), l);
break;
}
} catch (IOException x) {
lastException = x;
}
}
FormatString
接口的实现类,根据之前代码得知, 普通字符串是java.util.Formatter.FixedString
类型,而待替换的变量占位符是java.util.Formatter.FormatSpecifier
类型。java.util.Formatter.FormatString#index
方法,对应了上诉switch代码的不同分支,即不同的处理策略。fs.print((args == null ? null : args[last]), l);
即把对应位置的参数填充进来。原文:https://www.cnblogs.com/gxhunter/p/11296742.html