java常识1:弄清楚equals()和“==”
程序员文章站
2022-07-12 16:54:24
...
一、传统认知
运算 |
基本数据类型比较的对象 |
引用数据类型比较的对象 |
== |
值 |
堆内存空间 |
equals |
值 |
默认堆内存空间,覆写的方法除外 |
二、通过程序找问题
import com.leon.java.reflect.Person;
class Dog{
private String name ;
Dog(){}
Dog(String name){
this.name = name;
}
}
public class EqualsDemo<T> {
void test(T t1,T t2){
System.out.println("t1是否==t2:" + (t1 == t2));
System.out.println("t1是否equals t2:" + (t1.equals(t2)));
}
public static void main(String[] args) {
// == 比较 基本类型
System.out.println("\n--------比较基本类型-------");
System.out.println("\n1.比较Byte");
new EqualsDemo<Byte>().test((byte)123,(byte)123);
System.out.println("\n2.比较Short");
new EqualsDemo<Short>().test((short)123,(short)123);
System.out.println("\n3.比较Integer");
new EqualsDemo<Integer>().test(1,1);
System.out.println("\n4.比较Long");
new EqualsDemo<Long>().test(123L,123L);
System.out.println("\n5.比较Float");
new EqualsDemo<Float>().test(1.4f,1.4f);
System.out.println("\n6.比较Double");
new EqualsDemo<Double>().test(1.433333,1.433333);
System.out.println("\n7.比较char");
new EqualsDemo<Character>().test('a','a');
System.out.println("\n8.比较Boolean");
new EqualsDemo<Boolean>().test(true,true);
//发现的问题1:浮点型两个“相同的数” == 比较结果不同。解决方法:浮点型数据比较是否相等时,转化成包装类型,使用equals进行比较。
//比较引用类型
System.out.println("\n--------比较引用类型-------");
Dog d1 = new Dog("旺旺");
Dog d2 = new Dog("旺旺");
System.out.println("\n比较自定义的Dog类");
new EqualsDemo<Dog>().test(d1,d2);
System.out.println("\n比较String");
new EqualsDemo<String>().test("aaa","aaa");
//发现问题:String是引用类型,==比较引用类型时,比较的应该是地址才对。为什么在这里两个String对象的比较结果是true。
}
}
JDK1.8下输出结果为:
--------比较基本类型-------
1.比较Byte
t1是否==t2:true
t1是否equals t2:true
2.比较Short
t1是否==t2:true
t1是否equals t2:true
3.比较Integer
t1是否==t2:true
t1是否equals t2:true
4.比较Long
t1是否==t2:true
t1是否equals t2:true
5.比较Float
t1是否==t2:false
t1是否equals t2:true
6.比较Double
t1是否==t2:false
t1是否equals t2:true
7.比较char
t1是否==t2:true
t1是否equals t2:true
8.比较Boolean
t1是否==t2:true
t1是否equals t2:true
--------比较引用类型-------
比较自定义的Dog类
t1是否==t2:false
t1是否equals t2:false
比较String
t1是否==t2:true
t1是否equals t2:true
这里我们不难发现两个问题:
问题1:浮点型两个“相同的数” == 比较结果为什么不同?
问题2:String是引用类型,==比较引用类型时,比较的应该是地址才对。为什么在这里两个String对象的比较结果是true?
三、解决问题
1.浮点型数据判断是否相等
答:这个问题的由来比较古老,是浮点型这种数据类型的设计导致了这种情况。当然,JDK的开发人员也知道这个问题,于是他们提供了这样的解决方法:
意思是:只要参数传入的对象是Double类型,且当前对象和传入对象的“doubleToLongBits()”相同即认定为两者相等。
我们来看doubleToLongBits(double value)方法。
第一行就调用了另一个方法:
doubleToRawLongBits();
java.lang.Double.doubleToRawLongBits() 方法返回根据IEEE754浮点“双精度格式”位布局,不是非数字(NaN)值,返回指定浮点值的表示。它包括以下要点:
- 如果参数为正无穷大,其结果是 0x7ff0000000000000L.
- 如果参数为负无穷大,其结果是 0xfff0000000000000L.
- 如果参数为NaN,那么结果是长整型表示实际NaN值。doubleToLongBits方法不同,doubleToRawLongBits不垮所有的位模式NaN编码为一个单一的“规范”NaN值。
简单理解:
上面的内容有点多不想看,可以简单理解为:Double的equals()方法是通过将double型转换成long型变量,来进行数值比较的。
2.String是引用类型,==比较引用类型时,比较的应该是堆内存才对。为什么在这里两个String对象的比较结果是true?
答:java代码实际的执行引擎是jvm,jvm为String型变量提供了缓存机制,只要内容相同的String实例,不会重新创建对象,而是重用已经存在的对象。
推荐阅读
-
Java中 equals 和 == 的比较
-
DFS和BFS讲解及Leetcode刷题小结(1)(JAVA)
-
荐 JAVA13——容器(Map接口、Equals和hashcode、Set接口、容器存储数据练习、Iterator接口)
-
Java--equals和 == 的比较和equals()、HashCode()的重写
-
荐 java父类-Object类-equals与==-方法的重载和重写-游离块-this关键字
-
equals和==的区别_JAVA
-
java中“==“和equals()的区别详解
-
Java中为什么要重写hashCode方法和equals方法?
-
Java“求从1到10的阶乘的和”
-
【Java】请解释String类“==”和“equals”的区别