strings.xml中占位符类型错配或顺序错误会导致运行时崩溃,而非编译错误;%s仅接受string或对象(调用tostring),%d仅接受整型;多语言需用%1$s、%2$d等索引格式确保顺序正确。

strings.xml里%s和%d写错会直接崩溃
Android在运行时解析strings.xml中的占位符,如果格式符和实际传入参数类型不匹配(比如用%s接收一个int),String.format()会在调用时抛出IllegalFormatConversionException或MissingFormatArgumentException,不是编译报错,而是运行到那一行才崩。
-
%s只接受String、CharSequence或任何对象(自动调用toString()) -
%d只接受整型数字(int、long、Integer等),不能传String或double - 占位符顺序必须和
getString(R.string.xxx, arg1, arg2)中参数顺序严格一致 - 多占位符时别漏写,比如
"%s已下载%d条"必须传两个参数,少一个就报MissingFormatArgumentException
Java/Kotlin调用时传参类型要和占位符对得上
占位符是声明式约束,真正校验发生在Context.getString()内部调用String.format()那一刻。Kotlin里容易踩的坑是自动装箱和类型推断干扰。
- 传
count.toInt()给%d没问题,但传count.toString()给%d就会崩 - Kotlin中
val count = 5L是Long,传给%d可以(String.format支持long),但传给%s也合法——只是语义错 - Java里
getString(R.string.msg, 42)配%s不会编译报错,但运行时报错;IDE也不会高亮警告
示例:strings.xml:
<string name="download_status">%s已下载%d条</string>
Kotlin调用:
context.getString(R.string.download_status, "图片", totalCount)——
totalCount必须是整型,"图片"是字符串
需要格式化数字或日期?别硬塞进strings.xml
strings.xml里的占位符只做简单替换,不支持宽度、精度、本地化格式(比如千分位、小数位数、货币符号)。这些逻辑必须移出资源文件,在代码里用NumberFormat或DateFormat处理后再传入。
- 错误写法:
"共%d.2f元"——.2f在strings.xml里无效,%f本身也不被Android原生String.format支持(会抛UnknownFormatConversionException) - 正确做法:先用
NumberFormat.getCurrencyInstance().format(price)得到字符串,再作为%s参数传入 - 日期同理:用
SimpleDateFormat或android.text.format.DateFormat格式化成字符串,再塞进%s
多语言适配时占位符顺序可能不同
某些语言(如阿拉伯语、希伯来语)要求参数顺序调换,或者需要额外修饰词。Android支持通过%1$s、%2$d这种带序号的格式符来锁定位置,避免翻译时乱序。
- 基础写法
"%s下载了%d个文件"在阿拉伯语翻译里可能要改成“下载了%d个文件,由%s发起”,此时没序号就会错位 - 应统一用带索引的写法:
"%1$s下载了%2$d个文件",翻译时可写成"%2$d个文件由%1$s下载" - 索引从1开始,且必须和
getString()参数顺序一致;混用带序号和不带序号的格式符会导致IllegalArgumentException
这事容易被忽略——开发阶段只测中文,上线后小语种用户一打开就闪退,问题难复现也难定位。










