java中用==比较double或float包装对象本质是比较引用而非数值,因无缓存机制且自动装箱不复用普通数值对象,故即使值相同也多返回false;应使用double.compare()、float.compare()或math.abs()误差判断,高精度场景用bigdecimal.compareto()。

Java 中用 == 比较两个 Double 或 Float 包装对象是否相等,**本质上是在比较引用是否指向同一个对象,而不是数值是否相等**。这会导致大量看似“应该为 true”的比较返回 false,尤其在涉及自动装箱、构造器创建或跨类型操作时。
包装类没有缓存机制
Double 和 Float 类**不提供 -128 ~ 127 的值缓存**(不像 Integer)。这意味着:
- 每次自动装箱(如
Double d = 1.0;)都可能新建一个对象; - 用
new Double(1.0)或new Float(0.5f)创建的对象,必定是新实例; - 即使两个对象数值完全相同,
==也大概率返回false。
自动装箱不保证复用对象
虽然编译器对 Double d = 1.0; 这类写法会调用 Double.valueOf(1.0),但该方法内部仅对 NaN、±Infinity 等特殊值做轻量级复用,**对普通有限数值一律新建对象**。所以:
-
Double a = 0.1; Double b = 0.1;→a == b通常是false; -
Double a = Double.NaN; Double b = Double.NaN;→a == b仍是false(因为 NaN 不等于自身,且对象不同)。
类型不同或标度隐含差异也会破坏 ==
当混用 Float 和 Double,或涉及字符串构造的 BigDecimal 时,== 更不可靠:
-
new Float(1.0f).equals(new Double(1.0))是false(类型不同),而new Float(1.0f) == new Double(1.0)编译都不通过(类型不兼容); - 即使都是
Double,new Double("1.0") == new Double("1.00")是false(不同对象),而它们的equals()也是false(因BigDecimal风格的标度参与判断)。
正确做法:用 compare() 或数值比较逻辑
要安全判断两个浮点包装对象是否“数值相等”,应避免 == 和泛用 equals():
- 优先使用
Double.compare(d1, d2) == 0或Float.compare(f1, f2) == 0—— 它们按 IEEE 754 规则处理NaN、-0.0等边界情况; - 若需容忍误差(如计算结果),改用差值绝对值比较:
Math.abs(d1 - d2) ; - 对高精度业务(如金额),直接用
BigDecimal并调用compareTo()(compareTo(b) == 0才表示数值相等)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











