1.关于==和equals
1.1 对于==
- 如果作用于基本数据类型的变量时,则直接比较其存储的“值”是否相等;
- 如果作用于引用类型的变量,则比较的是所指向的对象的地址。
int x = 10;
int y = 10;
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(x == y); // 输出true
System.out.println(str1 == str2); // 输出false
1.2 equals方法
注:equals方法不能作用于基本数据类型的变量,equals方法继承自Object类,比较的是是否是同一个对象。
- 如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址。
- 诸如String、Date等对equals方法对equals方法进行了重写,比较的是所指向的对象的内容。
这里我自己定义了一个Student类,没有重写equals()方法,最后的输出结果是:false
在我重写了equals()方法后,输出结果变成了true。
2.关于==和equals进阶
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1.equals(str2));
System.out.println(str1 == str2);
根据上面所讲,第一个是true,第二个是false,确实如此,那继续看下面的例子:
String s1 = "abc";
String s2 = "abc";
System.out.println(s1.equals(s2));
System.out.println(s1 == s2);
这次的结果和上一个的是一样的吗?答案是:true true
为什么第二个会是true呢?
这就涉及到了内存中的常量池,常量池属于方法区的一部分,当运行到s1创建对象时,如果常量池中没有,就在常量池中创建一个对象"abc",第二次创建的时候,就直接使用,所以两次创建的对象其实是同一个对象,它们的地址值相等。
PS:当创建String类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋值给当前引用,如果没有就在常量池中重新创建一个String 对象。
那上一个例子中的
String str1 = new String("abc");
是怎么回事呢?
这里其实创建了两次对象,一次是在常量池中创建了对象"abc",一次是在堆内存中创建了对象str1,所以str1和str2的地址值不相等。
初步了解在JVM中的内存分配知识
在JVM中,内存分为堆内存跟栈内存。他们二者的区别是: 当我们创建一个对象(new Object)时,就会调用对象的构造函数来开辟空间,将对象数据存储到堆内存中,与此同时在栈内存中生成对应的引用,当我们在后续代码中调用的时候用的都是栈内存中的引用。
参考: