choiceformat 通过分段函数逻辑将数字映射到文本分支:每个分支由下限值和对应文本组成,匹配规则为“大于等于该下限且小于下一个下限”,默认分支用∞表示。

MessageFormat 本身不直接支持“复数”或“性别”这类语义化选择,但它通过 ChoiceFormat 子格式实现了基于数值区间的条件文本映射——这是实现变量多元化选择格式的核心机制。
ChoiceFormat 是怎么工作的
它把一个数字映射到预定义的文本分支,靠的是“分段函数”逻辑:每个分支由一个下限值 + 对应文本组成,匹配规则是“大于等于该下限,且小于下一个下限”。默认分支用 符号表示。
{0, choice, 0#无库存|1#仅剩1件|2 中,<code>0匹配 0,1匹配 1,2 匹配所有 ≥2 的值- 注意:区间必须严格递增,且不能有重叠或空隙,否则行为不可预测
- ChoiceFormat 不处理字符串或枚举,只认
double类型数值(传入整数会自动转为 double)
在 MessageFormat 中嵌入 ChoiceFormat 的两种方式
一种是声明式写在模板里(推荐用于简单场景),一种是编程式绑定(适合复用或动态配置)。
-
模板内联写法:
String pattern = "消息提醒:{0, choice, 0#没有新消息|1#有1条新消息|2<br>直接调用 <code>MessageFormat.format(pattern, count)即可 -
对象绑定写法:先构造
ChoiceFormat实例,再用setFormatByArgumentIndex()挂载到MessageFormat对象上
适合需要多次复用同一规则、或规则来自配置文件的场景
常见误区与避坑提示
看似简单,但实际使用中容易出错的点集中在引号、类型和边界上。
- 模板里的单引号必须成对出现,否则会破坏解析;例如想显示
“剩余1件”,要写成'剩余1件',而不是"剩余1件"或漏掉引号 - 传入参数必须是数字类型(
int、long、double都可),传String或null会导致IllegalArgumentException - 不要试图用 ChoiceFormat 做非数值判断(比如 gender、status),那是
select类型的职责——Java 原生 MessageFormat 不支持 select,需借助Intl.MessageFormat等第三方库
中文场景下的实用建议
中文虽无语法复数,但仍有“量变引发质变”的表达需求,比如提示语、状态描述、评分等级等。
- 库存类:
0#缺货|1#仅剩1件|5 - 评分类:
0#差评|2.5#一般|4.0#好评|4.8 - 消息数:
0#暂无通知|1#1条未读|10(注意这里 {0} 在子格式中仍可引用原参数)










