要想了解==和equals 的区别 ,首先要了解“值”在jvm中的存储结构。java
值类型是存储在内存中的堆栈(之后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其自己则存储在堆中eclipse
==操做比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。jvm
注意 此处的equals为重写Object以后的方法工具
equals操做表示的两个变量是不是对同一个对象的引用,即堆中的内容是否相同。测试
==比较的是2个对象的地址,而equals比较的是2个对象的内容。this
显然,当equals为true时,==不必定为true;spa
java的基本数据类型,也称为原始的数据类型。它们分别是:
byte, short, char, int, long, float, double, boolean .
基本数据类型进行 “==” 比较时,比较的是 它们的值 是否相同。
例如:code
int a = 10; int b = 10 System.out.println(" (a == b) = " + (a == b));
输出的结果为真。
另外须要注意的是,对于基本类型而言,它们没有 equals() 方法,你们别上当啊。对象
1) 当 两个对象使用 “==” 进行比较时,比较的是它们在 内存中存放的地址。 也就是说,除非是 同一个new() 出来的两个对象(内存地址相同), 不然比较的结果都是false。具体测试代码以下:继承
public class Main { public static void main(String args[]) { Worker worker1 = new Worker(); //worker2 是 worker1 的引用,同指向一个内存空间。 Worker worker2 = worker1; System.out.println("(worker1 == worker2) : " + (worker1 == worker2)); System.out.println("-------------------------"); Worker worker3 = new Worker(); //worker3 与 worker4 都是调用new 产生的对象,不指向同一个内存空间。 Worker worker4 = new Worker(); System.out.println("(worker3 == worker4) : " + (worker3 == worker4)); } } class Worker { private String name; private double salary; public Worker() { this.name = "echo"; this.salary = 0.0; } public Worker(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } } 输出的结果: (worker1 == worker2) : true ------------------------- (worker3 == worker4) : false
2) 你们都知道java的全部类 都是从 java.lang.Object 这个类继承下来,而Object 类中本来就有一个 equals() 方法。首先,咱们来看看源代码中 Object 类的equals() 方法。具体代码以下:
public boolean equals(Object obj) { return (this == obj); }
能够发现,默认状况下,当咱们调用equals() 方法时,也仍然是比较两个对象 是否指向同一块内存空间。 咱们 稍微 修改 上面的代码,进行测试。具体代码以下:
public class Main1 { public static void main(String args[]) { Worker worker1 = new Worker(); //worker2 是 worker1的引用,同指向一个内存空间。 Worker worker2 = worker1; System.out.println("worker1.equals(worker2) : " + worker1.equals(worker2)); System.out.println("-------------------------"); Worker worker3 = new Worker(); //worker3 与 worker4 都是调用new 产生的对象,不指向同一个内存空间。 Worker worker4 = new Worker(); System.out.println("worker3.equals(worker4) : " + worker3.equals(worker4)); } } class Worker { private String name; private double salary; public Worker() { this.name = "echo"; this.salary = 0.0; } public Worker(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } } 运行结果以下: worker1.equals(worker2) : true ------------------------- worker3.equals(worker4) : false
上文说了,String类重写了 equals() 方法,当调用equals()方法比较两个String对象时,比较的是其内容,那 怪异二字 从何而来呢? 且看下面代码:
public class Main2 { public static void main(String args[]) { String s1 = "hello world"; String s2 = "hello world"; System.out.println("s1.equals(s2) : " + s1.equals(s2)); System.out.println("(s1 == s2) : " + (s1 == s2)); } } 运行结果以下: s1.equals(s2) : true (s1 == s2) : true 输出结果说明,s1 与 s2 同指向一个 String对象。
先不着急,咱们再修改一下上面代码:
public class Main3 { public static void main(String args[]) { String s1 = "hello world"; String s2 = new String("hello world"); System.out.println("s1.equals(s2) : " + s1.equals(s2)); System.out.println("(s1 == s2) : " + (s1 == s2)); } } 运行结果: s1.equals(s2) : true (s1 == s2) : false 输出结果说明,s1 与 s2 不属于同一个String对象。
为何出现上面这个怪异的问题?
原来,程序在运行的时候会建立一个字符串缓冲池。
当使用 String s2 = “hello world” ,
这样的表达是建立字符串的时候,程序首先会在这个String缓冲池中寻找相同值的对象,在第一个程序中,s1先被放到了池中,因此在s2被建立的时候,程序找到了具备相同值的 s1,将s2引用 s1所引用的 对象 “hello world”。
第二段程序中,使用了 new 操做符,它明白的告诉程序:”我要一个新的!不要旧的!”因而一个新的”hello world” Sting对象被建立在内存中。它们的值相同,可是内存地址不一样,一个在池中游泳,另外一个在岸边休息。
事情还没完,在看看下面这个例子。
public class Main4 { public static void main(String[] args) { String s1 = "hello world"; String s2 = new String("hello world"); s2 = s2.intern(); System.out.println("s1.equals(s2) : " + s1.equals(s2)); System.out.println("(s1 == s2) : " + (s1 == s2)); } } 运行结果以下: s1.equals(s2) : true (s1 == s2) : true
怎么会这样???
原来,java.lang.String的intern()方法 ,例如 “abc”.intern()方法的返回值仍是字符串”abc”,表面上看起来好像这个方法没什么用处。但实际上,它作了个小动做:检查字符串池里是否存在”abc”这么一个字符串,若是存在,就返回池里的字符串;若是不存在,该方法会 把”abc”添加到字符串池中,而后再返回它的引用。