前言
==和equals是咱们面试中常常会碰到的问题。那么它们之间有什么分割和区别呢?明天咱们就来聊聊吧!
问题
这里先抛出一些比拟典型口试问题:
int x = 10;int y = 10;String str1 = new String("abc");String str2 = new String("abc");String str3 = "abc";String str4 = "abc";System.out.println(x == y); // 输入?System.out.println(str1 == str2); // 输入?System.out.println(str1.equals(str2)); // 输入?System.out.println(str3 == str4); // 输入?System.out.println(str1 == str3); // 输入?System.out.println(str1.equals(str3)); // 输入?Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;System.out.println(f1 == f2);// 输入?System.out.println(f3 == f4);// 输入?
注释
咱们通常就是说"=="用来判断两个变量之间的的值是否相等。变量又分为根本数据类型变量和援用类型。如果是根本数据类型的变量间接比拟值而援用类型要比拟对应的援用的内存的首地址。而equals办法 艰深来说就是用来比拟两个对象长得是否一样。判断两个对象的某些特色(内容)是否一样。实际上就是调用对象的equals办法进行比拟。那么咱们来看看equals办法吧!
equals办法其实是属于Object类的办法。因为Object类是所有类的间接或间接父类,也就是说所有的类中的equals()办法都继承自Object类,而通过源码咱们发现,Object类中equals()办法底层实现其实就是是"=="号。
public boolean equals(Object obj) { return (this == obj);}
那么,在所有没有重写equals()办法的类中,调用equals()办法其实和应用"=="号的成果一样,也是比拟的对象地址值,然而,Java提供的所有类中,绝大多数类都重写了equals()办法,重写后的equals()办法个别都是比拟两个对象的值,比方String类,Date类,根本数据类型的包装类等。能够看哈String类的源码:
public boolean equals(Object var1) { if (this == var1) { return true; } else { if (var1 instanceof String) { String var2 = (String)var1; int var3 = this.value.length; if (var3 == var2.value.length) { char[] var4 = this.value; char[] var5 = var2.value; for(int var6 = 0; var3-- != 0; ++var6) { if (var4[var6] != var5[var6]) { return false; } } return true; } } return false; } }
解决
看了下面的形容,置信你能够做对或者答复起大多数这类的问题。然而还须要留神以下两点:
String str3 = "abc";String str4 = "abc";System.out.println(str3 == str4); // 输入true
- 这里为什么会是true呢?按理说str3和str4是两个对象,"=="比拟的是地址,应该会是false才对。如果你是这么想的,那你就不是很理解String类。String类,咱们都晓得它是不可变的字符序列,存储在常量池中,所以当你申明了一个str3="abc"时,就会在常量池中开拓一个内存空间来寄存"abc",下次再申明时,就会在常量池中去找,有,就间接把以后地址赋给变量,没有,就再创立。因而,此处的str3和str4是指向的同一个内存地址。
Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;System.out.println(f1 == f2);// 输入trueSystem.out.println(f3 == f4);// 输入false
看到下面的答案是不是感到非常的惊讶。其实这里暗藏着一个知识点。就是包装类的缓存问题。上面简略形容一下:
整型、char类型所对应的包装类,在主动装箱时,对于-128~127之间的值会进行缓存解决。当然其目标就是提高效率。
缓存解决的原理为:如果数据在-128~127这个区间,那么在类加载时就曾经为该区间的每个数值创立了对象,并将这256个对象寄存到一个名为cache的数组中。每当主动装箱过程产生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则间接获取数组中对应的包装类对象的援用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。
此处以Integer类为例,源码参考:
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); // 超过范畴就是new的Integer对象}
这段代码中咱们须要解释上面几个问题:
1. IntegerCache类为Integer类的一个动态外部类,仅供Integer类应用,作用就是初始化数组cache的,这个过程会在类加载时实现。感兴趣能够去看哈源码,这里就不再粘贴了。 2. 个别状况下 IntegerCache.low为-128,IntegerCache.high为127,IntegerCache.cache为外部类的一个动态属性。
看到这,置信你对下面抛出的问题,曾经能够迎刃而解。答案参考:
int x = 10; int y = 10; String str1 = new String("abc"); String str2 = new String("abc"); String str3 = "abc"; String str4 = "abc"; System.out.println(x == y); // 输入true System.out.println(str1 == str2); // 输入false System.out.println(str1.equals(str2)); // 输入true System.out.println(str3 == str4); // 输入true System.out.println(str1 == str3); // 输入false System.out.println(str1.equals(str3)); // 输入true Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150; System.out.println(f1 == f2);// 输入true System.out.println(f3 == f4);// 输入false
最初,最近很多小伙伴找我要Linux学习路线图,于是我依据本人的教训,利用业余时间熬夜肝了一个月,整顿了一份电子书。无论你是面试还是自我晋升,置信都会对你有帮忙!
收费送给大家,只求大家金指给我点个赞!
电子书 | Linux开发学习路线图
也心愿有小伙伴能退出我,把这份电子书做得更完满!
有播种?心愿老铁们来个三连击,给更多的人看到这篇文章
举荐浏览:
- 干货 | 程序员进阶架构师必备资源免费送
- 神器 | 反对搜寻的资源网站