Java对象的相等判定问题与equals方法详解

编程入门 行业动态 更新时间:2024-10-14 14:19:24

Java对象的相等判定问题与equals方法<a href=https://www.elefans.com/category/jswz/34/1770044.html style=详解"/>

Java对象的相等判定问题与equals方法详解

1. Integer

首先我们来看以下这段代码的运行结果:

package com.yyj;public class Equivalence {public static void main(String[] args) {testIntEqual(127);testIntEqual(128);/** [127] Auto: true true* [127] valueOf: true true* [127] Integer: false true* [127] Int: true* [128] Auto: false true* [128] valueOf: false true* [128] Integer: false true* [128] Int: true*/}private static void testIntEqual(int value) {// 第一种定义方式,利用了自动装箱特性,推荐该写法Integer a1 = value;Integer b1 = value;System.out.printf("[%d] Auto: %b %b\n", value, a1 == b1, a1.equals(b1));// 第二种定义方式Integer a2 = Integer.valueOf(value);Integer b2 = Integer.valueOf(value);System.out.printf("[%d] valueOf: %b %b\n", value, a2 == b2, a2.equals(b2));// 第三种定义方式,Java9之后已弃用,效率远不如valueOfInteger a3 = new Integer(value);Integer b3 = new Integer(value);System.out.printf("[%d] Integer: %b %b\n", value, a3 == b3, a3.equals(b3));// 第四种定义方式,不使用包装类,无equals方法int a4 = value;int b4 = value;System.out.printf("[%d] Int: %b\n", value, a4 == b4);}
}

对于参数值127,== 操作符只在使用 new 创建对象的方式上判定两个数为 false,这是因为操作符 ==/!= 比较的是对象的引用,虽然参与比较的两个引用包含的内容相同,但他们指向了内存中的不同对象。注意这种定义方式在 Java9 之后已经被废弃,因为其效率远不如使用 valueOf 方法。

对于参数值128,可以发现所有创建方式创建的两个相同值的 Integer 对象在 == 操作符的判定下均为 false,这是因为出于效率的原因,Integer 会通过享元模式来缓存范围在-128~127内的对象,因此多次调用 Integer.valueOf(127) 生成的其实是同一个对象,而在此范围之外的值则不会这样,即每次调用 Integer.valueOf(128) 返回的都是不同的对象。

因此在使用 Integer 的时候如果需要比较值是否相等应该只是用 equals 方法。

2. Double

我们再来看下面这段代码:

package com.yyj;public class Equivalence {public static void main(String[] args) {testDoubleEqual(0, 0);testDoubleEqual(0, Double.MIN_VALUE);testDoubleEqual(Double.MAX_VALUE, Double.MAX_VALUE - Double.MIN_VALUE * 1000000);/** [0.000000e+00 | 0.000000e+00] double: true* [0.000000e+00 | 0.000000e+00] Auto: false true* [0.000000e+00 | 0.000000e+00] valueOf: false true* [0.000000e+00 | 0.000000e+00] Double: false true* [0.000000e+00 | 4.900000e-324] double: false* [0.000000e+00 | 4.900000e-324] Auto: false false* [0.000000e+00 | 4.900000e-324] valueOf: false false* [0.000000e+00 | 4.900000e-324] Double: false false* [1.797693e+308 | 1.797693e+308] double: true* [1.797693e+308 | 1.797693e+308] Auto: false true* [1.797693e+308 | 1.797693e+308] valueOf: false true* [1.797693e+308 | 1.797693e+308] Double: false true*/}private static void testDoubleEqual(double a, double b) {System.out.printf("[%e | %e] double: %b\n", a, b, a == b);Double a1 = a;Double b1 = b;System.out.printf("[%e | %e] Auto: %b %b\n", a1, b1, a1 == b1, a1.equals(b1));Double a2 = Double.valueOf(a);Double b2 = Double.valueOf(b);System.out.printf("[%e | %e] valueOf: %b %b\n", a2, b2, a2 == b2, a2.equals(b2));Double a3 = new Double(a);Double b3 = new Double(b);System.out.printf("[%e | %e] Double: %b %b\n", a3, b3, a3 == b3, a3.equals(b3));}
}

理论上浮点数的比较应该是很严格的,即两个数值之间即使有极小的不同也应该不相等。

例如0和 Double.MIN_VALUE 相比较并不相等,但是 Double.MAX_VALUE 减去一百万倍的 Double.MIN_VALUE 却仍等于 Double.MIN_VALUE,这是因为当一个非常大的数值减去一个相对较小的数值时,非常大的数值并不会发生显著变化,这叫做舍入误差,误差的产生原因是因为机器不能存储足够的信息来表示一个大数值的微小变化。

3. 自定义类

现在你是不是以为在比较对象内容是否相等的情况下都一律用 equals 函数即可?但是并没有这么简单。看下面这段代码:

package com.yyj;public class Equivalence {public static void main(String[] args) {testClassEqual();}private static void testClassEqual() {A a1 = new A(10);A a2 = new A(10);System.out.println(a1.equals(a2));  // falseB b1 = new B(10);B b2 = new B(10);System.out.println(b1.equals(b2));  // true}
}class A {int val;A(int val) {this.val = val;}
}class B {int val;B(int val) {this.val = val;}public boolean equals(Object o) {B tempB = (B)o;  // 将Object对象转型为Breturn this.val == tempB.val;}
}

我们创建了两个类 A 的对象,且值相等,但是 equals 方法返回的结果为 false,这是因为 equals 方法的默认行为是比较引用,如果想比较内容必须像类 B 那样重写 equals 方法。

因此实际上其实是大多数标准库会重写 equals 方法来比较对象的内容而不是他们的引用。

更多推荐

Java对象的相等判定问题与equals方法详解

本文发布于:2023-12-03 19:35:45,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1657018.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:详解   对象   方法   Java   equals

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!