在初学 java 时,可能会经常碰到下面的代码:
String s1 = new String ("hello") ;
String s2 = new String ("hello");
System.out.println(s1==s2); // false
System.out.println(s1.equals (s2)); // true
为什么第 4 行和第五行的输出结果不一样? == 和 equals 方法之间的区别是什么?
一、关系操作符 " == " 到底比较的是什么?
下面这句话是摘自 《 java 编程思想 》一书中的原话:
" 关系操作符生成的是一个 boolean 结果,它计算的是操作数的值之间的关系 "
说简单点,== 就是用来比较值是否相等。
例子:
package com.darksnow.test;
public class Demo1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int n = 3 ;
int m = 3 ;
System.out.println(n==m); // true
String s1 = new String("hellom");
String s2 = new String("hellom");
String s3 = new String("hellom");
System.out.println(s2==s3); // false
s2 = s1 ;
s3 = s1 ;
System.out.println(s2==s3); // true
}
}
输出的结果为 true false true
n == m 结果为 true ,这个很容易理解,变量 n 和变量 m 存储的值都为 3 ,肯定是相等的。而为什么 s2 和 s3 两次比较的结果不同?
这个其实只需要理解基本数据类型变量和非基本数据类型变量的区别。
在 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 " )
对于这八种基本数据类型的变量,变量直接存储的是 “ 值 ”,因此在用关系操作符来进行比较时,比较的就是 “ 值 ”
本身。要注意浮点型和整型都是符号类型的,而 char 是无符号类型的 ( char 类型取值范围为 0 ~ 2 ^ 16 - 1).
也就说比如:
int n = 3 ;
int m = 3 ;
变量 n 和变量 m 都是直接存储的 “ 3 ” 这个数值,所以用 == 比较的时候结果是 true 。
而对于非基本数据类型的变量,在一些书籍中称作为引用类型的变量。比如 s1 s2 s3 就是引用类型的变量,引用类型的变量存储的并不是 “ 值 ” 本身,而是于其关联的对象在内存中的地址。比如下面这行代码:
String s2 ;
这句声明了一个引用类型的变量,此时它并没有和任何对象关联。
而通过 new String (" hellom ") 来产生一个对象(也称作为类 String 的一个实例),并将这个对象和 s2 进行绑定:
s2 = new String (" hellom ");
那么 s2 指向了一个对象(很多地方也把 s2 称作为对象的引用),此时变量 s2 中存储的是它指向的对象在内存中存储地址,并不是 “ 值 ” 本身,也就是说并不是直接存储的字符串 “ hellom ”。这里面的引用和 C/C++ 中的指针很类似。
因此在用 == 对 s2 和 s3 进行第一次比较时,得到的结果是 false 。因此它们分别指向的是不同的对象,也就是说它们实际存储的内存地址不同。
而在第二次比较时,都让 s2 和 s3 指向 s1 指向的对象,那么得到的结果毫无疑问是 true 。
二、equals 比较的又是什么 ?
equals 方法是基类 Object 中的方法,因此对于所有继承 Object 的类的都会有该方法,为了更直观地理解equals方法的作用,直接看 Object 类中 equals 方法的实现
在Object类中,equals方法是用来比较两个对象的引用是否相等,即是否指向同一个对象。
String类对equals方法进行了重写,用来比较指向的字符串对象所存储的字符串是否相等。
其他的一些类诸如Double,Date,Integer等,都对equals方法进行了重写用来比较指向的对象所存储的内容是否相等。
总结来说:
1)对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
如果作用于引用类型的变量,则比较的是所指向的对象的地址
2)对于equals方法,注意:equals方法不能作用于基本数据类型的变量
如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。



