源码分析
前两天小编去面试了,被问到一个非常基础的问题,==与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的一些理解,欢迎大家来分享自己的理解哦,促进学习,哈哈哈。
今天的文章面试==和equals的区别 hashcode_c++面试题目100及最佳答案「建议收藏」分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/87908.html