源码分析
前两天小编去面试了,被问到一个非常基础的问题,==与equals的区别,可小编只是回答了一部分,一个比较基本数据类型,一个是比较引用数据类型,其他的就给忘了,回家之后,小编就百度了一下这个知识点,今天就总结了一下。
我们先来看一段代码:
public static void main(String[] args) {
String s1 = "meng"; String s2 = "meng"; System.out.print("==的比较结果是:"); System.out.println(s1==s2); System.out.println("equals的比较结果是:"+s1.equals(s2)); }
我们再来看一段代码
public static void main(String[] args) {
String s1 = new String("meng"); String s2 = new String("meng"); System.out.print("==的比较结果是:"); System.out.println(s1==s2); System.out.println("equals的比较结果是:"+s1.equals(s2)); }
我们看到两次控制台输出的结果不一样,第一次的时候两个都是true,第二次的时候“==”比较的结果是false,“equals”比较的结果是true,这主要是因为双等号在比较引用类型的时候主要是比较地址。
接下来我们详细说一说==的比较。
当双等号比较的是基本数据类型的时候,比较的数据的值,但是如果比较的是引用数据类型的时候比较的就是数据的内存地址,就比如上面的案例。那为什么上面两个例子比较的结果不同呢?
首先,我们先画图模拟第一种情况。代码“String s1 = ‘meng’”,是jvm现在堆区中的常量池中先创建一个内容为“meng”的地址值,然后再栈去再创建一个S1的变量为其分配一块空间,然后由栈区的S1指向堆内存的“meng”的地址值。而不是直接给S1赋值为meng。
所以,在执行性代码“String s2 = ‘meng’”的时候,会现在堆内存的常量池中查询有没有“meng”的地址,如果没有的话,则会重新分配一块空间,如果有的话,就不会再重新分配一块新的空间了。但是仍然会在栈区重新分配一块空间并命名为“s2”,此时的s2会直接指向常量池中的meng,so,s1和s2指向的是同一个地址值,所以双等号判断会为false。
接着,我们再来说一说第二种情况,由上述代码可见,我们是重新new了一下,要记住,只要是new的时候,就会重新创建出一个对象,也就是说jvm会在堆区重新开辟出一块空间内容为“meng”,然后会让s2指向重新开辟的这个地址值,所以,s1和s2的内存地址不一样,所以使用双等号再次比较的时候就会是false了。
不知道大家有没有想过,为什么equals方法在比较引用类型的时候就是纯粹的再比较值,而不是比较引用的地址呢?这个得追溯到equals方法的源码了,下面就是我复制过来的源码,以及自己的一点理解。
//我们知道在Java中,所有的类都是直接或者间接的继承Object类,所以这里传入一个Object类型会比较方便一些 public boolean equals(Object anObject) {
//就是说让s1和s2进行双等号比较,如何二者内存地址相同的话,就会跳出并返回true,如果地址不同,会执行下一个if判断 if (this == anObject) {
return true; } //instanceof是对传入值的类型的一个判断,即s2若是String类型的话,返回true,继续执行下面代码,如果不是,跳出返回false if (anObject instanceof String) {
//把s2转化为String类型 String anotherString = (String)anObject; //这里省略了this,n指的是s1的长度 int n = value.length; //判断s1和s2的长度是否相同 if (n == anotherString.value.length) {
//把s1拆分一下,并且把拆分的结果放到v1这个字符数组里,即['m','e','n','g'] char v1[] = value; //同理,把s2拆分放到数组v2里 char v2[] = anotherString.value; int i = 0; //将两个数组的值进行比较,如果有一个不同,则返回false while (n-- != 0) {
if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
看完源码我们就知道为什么equals方法是比较引用类型的值了,这是因为底层源码的原因,就感觉,源码很重要。
equals方法的特性
- 自反性:对于任何非空引用x来说,比较它本身x.equals(x)都返回true。
- 对称性:对于非空引用x、y,x.equals(y)若返回true,那么y.equals(x)也是返回true。
- 传递性:对于非空引用x、y、z来说,如果有x.equals(y)返回true,y.equals(z)返回true,那么就有x.equals(z)返回true。
- 一致性:对于非空引用x、y,如果x.equals(y)返回true相等的话,那么他们始终保持相等。
- 非空性:对于非空引用x,那么x.equals(null)必然会返回false。
以上就是梦梦对==和equals的一些理解,欢迎大家来分享自己的理解哦,促进学习,哈哈哈。
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/163496.html