Java中equals与==区别
关系操作符 ==
首先Java中的数据类型分为
- 基本类型
- 引用类型
在Java中有八种基本数据类型:
- 浮点型:float(4 byte), double(8 byte)
- 整型:byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)
- 字符型: char(2 byte)
- 布尔型: boolean(JVM规范没有明确规定其所占的空间大小,仅规定其只能够取字面值”true”和”false”)
对于这八种基本数据类型的变量,变量直接存储的是“值”。
所以,在八种基本类型中使用关系操作符 == 来进行比较时,比较的就是“值”本身。
除了基本类型,Java中还有引用类型
在Java中,引用类型的变量存储的并不是“值”本身,而是与其关联的对象在内存中的地址。
比如下面这行代码
String str1;
这句话声明了一个引用类型的变量,此时它并没有和任何对象关联。
而通过 new 来产生一个对象,并将这个对象和str1进行绑定:
str1= new String("hello");
那么 str1 就指向了这个对象,此时引用变量str1中存储的是它指向的对象在内存中的存储地址,并不是“值”本身,也就是说并不是直接存储的字符串”hello”。这里面的引用和 C/C++ 中的指针很类似。
小结
因此,对于关系操作符 ==:
- 若操作数的类型是基本数据类型,则该关系操作符判断的是左右两边操作数的值是否相等
- 若操作数的类型是引用数据类型,则该关系操作符判断的是左右两边操作数的内存地址是否相同。也就是说,若此时返回true,则该操作符作用的一定是同一个对象。
equals方法
1、来源
equals方法是基类Object中的实例方法,因此对所有继承于Object的类都会有该方法。2、equals方法的作用
为了更直观地理解equals方法的作用,我们先看Object类中equals方法的实现。
public boolean equals(Object obj) { return (this == obj); }通过代码可以看到,Object类里的equals方法也就是直接使用==。
但我们都知道,下面代码输出为 true:
public class Main {
public static void main(String[] args) {
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1.equals(str2));
}
}
再看一下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; // 逐字符判断是否相等,如果有一个字符不相等,则返回false while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } // 如果所有字符都相等,则返回true return true; } } // 如果类型不相等,直接返回false return false; }
可以看到String重写了equals()方法
使用equals方法,内部实现分为三个步骤:
- 比较引用是否相同(是否为同一对象)
- 判断类型是否一致
- 判断长度是否一致
- 比较内容是否一致
小结
- String重写了equals()方法
- 在String中使用equals()时比较的是字符串的值是否相等
------------------------------------------------------------------------------------------
String对象的创建有两种方式
方法一
对象不同,内容相同
"=="返回false,equals返回true
String s1 = new String("java");
String s2 = new String("java");
System.out.println(s1==s2); //false
System.out.println(s1.equals(s2)); //true
同一对象
"=="和equals结果相同
String s1 = new String("java");
String s2 = s1;
System.out.println(s1==s2); //true
System.out.println(s1.equals(s2)); //true
方法二
如果值不相同,则肯定不是相同的对象
所以在这种情况下"==" 和equals结果一样
String s1 = "java";
String s2 = "java";
System.out.println(s1==s2); //true
System.out.println(s1.equals(s2)); //true
使用方法二创建String时,首先冲缓冲池中找有没有相同的值,如果有则直接指向它。所以这里s1==s2为true
小结
两个语句都是返回一个String对象的引用, 但JVM处理的方式不一样.
- 方法一: JVM 马上在堆区中创建String对象, 然后将对象的引用返回.(并不会添加至 String Pool 中, 除非显示的调用 String的intern方法)
- 方法二: JVM 首先在 String Pool 中通过String的 equals 方法查找对象池中是否有该String对象. 如果有,则直接返回而不会再重新创建; 如果没有, JVM 则在堆区中创建新的String对象, 将其引用返回, 同时将该引用添加至String Pool中.
下一篇: Java学习(七)之异常