要想了解==和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」添加到字符串池中,而後再返回它的引用。