刚开始学Java的时候,遇到equals比较和==比较有时候结果总是让人惊讶,如果是以前没有接触过编程,不明白内存分配,每次都是稀里糊涂的记住一些结果。这种是true那种是false,但具体是为什么,具体自己应该怎么去分析才能分析出程序应该有的结果,今天我们就从Java内存分配的角度来聊聊。
先上代码:
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1==str2);
System.out.println(str1!=str2);
结果false true
==比较str1和str2的结果是false,也就是他们是不等的。这里首我们要明白==比较的是什么,==比较的是他们在内存中的地址,也就是他们是否是同一个对象。我们来看String str1 = new String("abc");这句话做了什么事,遇到new关键字会做三件事:
1、 开辟一块堆内存空间用于存放对象(这块空间会有一个地址)
2、 创建一个新的对象放入开辟的内存空间
3、 将str1引用指向这块内存空间
我们看一下Java虚拟机运行时数据区内存划分(图片来源深入理解Java虚拟机)
下面是简易的内存分配
从这里可以看出str1和str2指向的是两块不同的内存区域,也就是两个不同的对象,所以==比较为false。但我们想要的是并不是想知道他们是不是同一个对象,我们想知道它们的值想不想等,这时候就需要使用到equals方法。比如上面的程序System.out.println(str1.equals(str2));就会出现true,这是比较的才是它们的值。下面是String类源码中实现的equals()
public boolean equals(Object anObject) {
//比较是否是同一个对象,如果是同一个对象那一定是true
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;
}
我们知道String是Java的类,如果是自己创建的类呢,还会是一样的效果吗。比如创建一个Value
class Value{
int i;
}
public class TestDemo {
public static void main(String[] args) {
Value v1 = new Value();
Value v2 = new Value();
v1.i = v2.i = 100;
System.out.println(v1.equals(v2));
}
}
结果是false,这又是为什么呢。不知道你有没有注意到我们写的Value类中根本没有equals方法,结果却能调用,那一定是调用了父类Object中的方法,我们来看一下Object中equals方法是怎么写的。
public boolean equals(Object obj) {
return (this == obj);
}
返回了是否==,也就是equals方法的内部实现是判断是否==,这也与我们的本意不符。怎么办呢?这时候要想比较自己定义的类的实例是否相等,就必须重写equals方法,具体怎样才算相等,就看你自己的实现了。
class Value{
int i;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Value value = (Value) o;
return i == value.i;
}
@Override
public int hashCode() {
return i;
}
}
public class TestDemo {
public static void main(String[] args) {
Value v1 = new Value();
Value v2 = new Value();
v1.i = v2.i = 100;
System.out.println(v1.equals(v2));
}
}
输出结果true