Java中DecimalFormat将负号转为问号?同版本JDK不同环境输出不一致如何解决
问题根因
- 你没有给
DecimalFormat显式指定格式化规则对应的Locale,该类默认会读取当前操作系统的默认区域配置生成格式化符号:- 你本机的系统区域默认负号为ASCII标准的
-(U+002D),小数分隔符为逗号,所以输出符合预期 - 用户设备的系统区域配置使用了非ASCII的负号字符(比如Unicode数学减号U+2212、部分小语种自定义的负号标识),如果用户的运行输出环境不支持该字符的编码渲染,就会显示为乱码
?
- 你本机的系统区域默认负号为ASCII标准的
- 你和用户使用的OpenJDK 16版本核心逻辑不存在差异,Temurin发行版和官方OpenJDK的格式化模块代码完全一致,问题和JDK发行版无关。
修复方案
如果需要全局固定输出-0,043的格式,建议完全自定义格式化符号,彻底屏蔽系统Locale的影响,代码修改如下:
double s = -0.04374467357823164; // 手动定义格式化符号,完全不受系统配置影响 DecimalFormatSymbols customSymbols = new DecimalFormatSymbols(); customSymbols.setMinusSign('-'); // 固定负号为ASCII的短横线 customSymbols.setDecimalSeparator(','); // 固定小数分隔符为逗号 DecimalFormat numberFormat = new DecimalFormat("##.###", customSymbols); numberFormat.setRoundingMode(RoundingMode.DOWN); System.out.println("Formatted: " + numberFormat.format(s));
如果你的业务本身就是对应指定国家区域的格式规则,也可以直接显式指定对应Locale,比如法语区域默认就是逗号作为小数分隔符、ASCII短横线作为负号,写法如下:
double s = -0.04374467357823164; // 显式指定法语Locale,格式化规则固定 DecimalFormat numberFormat = new DecimalFormat("##.###", DecimalFormatSymbols.getInstance(Locale.FRANCE)); numberFormat.setRoundingMode(RoundingMode.DOWN); System.out.println("Formatted: " + numberFormat.format(s));
内容的提问来源于stack exchange,提问作者David Fr
相关产品推荐
相关产品推荐

