从四个方面谈一谈经典的==和equals的问题

时间:2021-07-18 13:56:39

由一个例子引出的四个方面谈一谈经典的==和equals的问题
代码:
private static void test(){
String a = “a”+”b”+1;
String b = “ab1”;
System.out.println(a==b);
}
关于这一段程序会输出的结果是什么?你可能会说是true或者false,那真正的答案是true;我们从下面4个方面来分析这个问题
1. 关于“==”是干什么的?
1.1 关于“==”
首先要知道“==”用于匹配内存单元上的内容,其实就是一个数字,计算机内部也只有数字。在java中,当“==”匹配的时候,其实就是对比两个内存单元的内容是否一样。
如果是原始类型byte、boolean、short、char、int、float、double等就是直接比较他们的值。
如果是引用(reference),比较的是引用的值,可以被认为是对象的逻辑地址。如果两个引用使用“==”比较操作,就是比较行营的两个对象的地址是否一样。如果一样则返回true,否则返回false。
2. 关于equals是干什么的?
2.1关于“equals”
说起equals方法,大家都不陌生,是在Object类中被定义的,他的定义就是默认使用“==”来匹配的。也就是说如果我们不重写equals方法,并且对应的父类中也都没有重写过equals,可以默认为是用equals使用的是比较对象的地址是否相同。
而equals之所以存在,是希望用户的子类去重写这个方法,实现对比值的功能。类似的String就实现了equals方法。自己去实现这个方法是因为当我们两个对象对比时只选取其中关键的业务属性上面来。确定他们是否是“一致的或者是相似的”,则返回true/false即可。
注:相似的理解
有时我们在一个情景业务条件下,并不一定需要绝对相同才可以认定为相同,比如我们都知道我们的亲子鉴定的结果,出来都没有100%的可能性,那现在就要发挥这个相似的作用了,我们可以规定只要他的报告相似度为98%以上,我就认为是亲生的即(返回true否则返回false)。也就是说,两个对象的值是否相等是自己的业务来决定的而不是java语言本身所决定的。
3. a和b在内存中是如何分配的(是怎样的)?
回到页首的例子中,其中等号说明a和b是指向同一块内存空间的,就想两个人拿到同一个公司的offer一样,所有答案才是true;
4. jvm在编译阶段的优化方案
a引用是通过“+”赋值的,b引用是直接赋值的,那为什么a和b会共享一个内存单元?这就是jvm的“编译时优化”。
当我们的编译器在编译代码String a = “a”+”b”+1,时会将其编译为String a =”ab1”;因为他们都是常量,编译器认为这3个常量的叠加会达到固定的值,无需运行时候进行技算,所有就会这样优化。
这样做的目的是我们把同样的业务逻辑放在一起执行,更能解决资源的均衡和辉煌。