1 ==是逻辑运算符
1.1 == 的基础数据类型比较
对于基本数据类型 (byte,short,char,int,long,float,double,boolean)的变量”==”比较的是两个变量的值是否相等。
public class Test {
public static void main(String[] args) {
int a = 1;
long b = 1;
Integer c = 1;
// a 会隐式转换从int 到 long。
System.out.println(a == b); // 输出: true
// c 会自动拆箱变成 int
System.out.println(a == c); //输出: true
// c 会自动拆箱变成 int,然后。隐式转换从int 到 long。
System.out.println(b == c); //输出: true
}
}
1.2 == 对于引用类型如,则比较的是该变量所指向的地址
1.2.1 String常量类型
public class Test {
public static void main(String[] args) {
String x = "mianshi";
String y = "mianshi";
// 字符串直接赋值给变量,该字符串会进入到常量池中,
// 第一次将 “mianshi”赋值给x的时候,会去常量池中找看有没有”mianshi”这个字符串,
// 如果有的话,就将a指向该字符串在常量池中的地址,如果没有则在常量池中创建,
// 第二次赋值 将 “mianshi”赋值给y的时候同样去常量池中找”mianshi”这个字符串,
// 然后将他的地址赋值给b.
System.out.println(x == y); // 输出: true
// z 也会执行常量mianshi
String z = x;
System.out.println(z == y); // 输出: true
}
}
1.2.1 堆上分配的内存
public class Test {
public static void main(String[] args) {
String x = new String("mianshi");
String y = new String("mianshi");
//当我们使用 String x = new String(“mianshi”)创建一个字符串对象时在内存里面是这样分配空间的,
// 首先会去常量池中找”mianshi”如果找到了再创建一个”mianshi”对象存到堆中,并且他的值指向堆中的”mianshi”,
// 如果没有找到则先在常量池中创建”mianshi”,再在堆内存开辟一块内存空间创建”mianshi”,并且他的值指向堆中的”mianshi”。
System.out.println(x == y); // 输出: false
// z指向的地址是常量的地址
String z = "mianshi";
System.out.println(x == z); // 输出: false
}
}
2 Equals
Equals方法是在Object类中定义的,所有的类都继承于Object类,所以所有的类都有equals方法。
equals方法的源码:
public class Object {
public boolean equals(Object obj) {
return (this == obj);
}
}
可以看到在Object类的equals方法中也是用的””来进行比较,所以在进行比较时它和””应该时等价的。
1)String覆盖了equals方法。我们看String的equals覆盖后的源码。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence{
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
}
public class Test {
public static void main(String[] args) {
String x = new String("mianshi");
String y = new String("mianshi");
System.out.println(x.equals(y)); // 输出: true
}
}
x…equals(y) 。先会执行this == anObject。即 == 的逻辑。这个时候x,y指向的是不同的堆地址。所以结果是false。接着往下走。if (v1[i] != v2[i]) 这一个是在逐个比较字符。
2) Integer 覆盖了equals代码
public final class Integer extends Number implements Comparable<Integer> {
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
}
public class Test {
public static void main(String[] args) {
Integer x = new Integer("8");
Integer y = new Integer("8");
System.out.println(x.equals(y)); // 输出: true
}
}
x.equals(y)。equals是y调用了.intValue()变成了一个基础的数据类型,然后和x的value比较,变成一个数值比较。
总结equals:
1、对象如果不覆盖,默认使用的是return (this == obj)。走的是==的比较。
2、对象如果覆盖了、使用的是自己的比较方式。
参考文章
《"=="和 equals 方法有什么区别》:https://zhuanlan.zhihu.com/p/77616029