Yahoo Answers is shutting down on May 4th, 2021 (Eastern Time) and beginning April 20th, 2021 (Eastern Time) the Yahoo Answers website will be in read-only mode. There will be no changes to other Yahoo properties or services, or your Yahoo account. You can find more information about the Yahoo Answers shutdown and how to download your data on this help page.

java的”==”和”equal”不了解

請問java的"=="和equal()有什麼差別?

請問java的"=="和equal()有什麼差別?

例如:

long int i=3;

double m=3.0;

Long a=new Long(3L);

Double x=Double(3.0);

System.out.println(i==a);

System.out.println(i==x);

System.out.println(a.equal(i));

請問輸出是true或flase,或compile/run error,及為什麼?

因為我自已輸出的結果和課本上的不一樣,所以我才問的。

那到底==是比什麼的,equal又是比什麼的?

好像通常參考形態都是用equal比較其物件的內容,

基本形態都是用"=="比較,"=="好像也比較是否兩者都參考同一個物件。

我不太了解,請專家指教,謝謝。

Update:

to:2樓的€ Solid dream builder,能否再解釋一下,謝謝!

那個覆寫equal的那個地方我不太懂,Car car1 = new Car(6);equal結果卻是false,是因為寫了equal的覆寫,才讓equal的結果為false嗎?

3 Answers

Rating
  • 1 decade ago
    Favorite Answer

    在此,先不解釋上述程式碼。

    ==

    使用基本型態時:

    基本型態做兩數比較是否相等時,毫無疑問的,使用==相等運算子。

    參考變數做比較時:

    要先了解電腦只知道0和1,不論是基本型態變數,或者是參考變數,請把變數想像成一個容器,該容器裝的是位元樣式,也就是

    int x = 6 → 110(位元),此為基本型態

    Object obj = new Object();

    obj 假設它所指向在heap記憶體區塊的記憶體位址為0x1234567(位元)

    上述應該不難了解,變數裡所放的都是位元樣式,因此需要釐清一個觀念就是,在java裡,只有【傳值】,沒有【傳址】,不論基本型態變數或參考變數,要把自己的值複製一份給另一個變數時,都是複製它們的位元樣式。所以當參考變數在使用==做比較時,是指兩物件是否有同時參考(指向)在heap(堆積)內的物件,即兩參考變數是否存放相同的記憶體位址(位元樣式)。

    equals(Object obj)

    equals()是用在兩物件比較是否儲存相同的內容值,以

    Integer i1 = new Integer(6);

    Integer i2 = new Integer(6);

    i1.equals(i2); 無疑地,一定是true。

    要了解,wrapper class有實作equals,因此它們可以用來比較兩wrapper object是否存放相同的內容值;順帶一提,String也有實作equals,所以它們在使用equals()時,沒有問題。

    equals()參考變數時: 我們一般所產生的物件由於沒有覆寫從Object繼承而來的equals(),因此當兩物件產生時,以下…

    Car car1 = new Car(6);

    Car car2 = new Car(6);

    假設建構子帶入的數值是表示車子編號,兩數值是一樣的,你應該認為car1.equals(car2)會是true,答案是錯的,因為沒藉由覆寫equals()去定義,兩個Car物件在什麼條件下,你認為是相等的。Object裡的equals()對兩物件的比較只用了==,所以由最上面所講的,car1==car2,這兩個參考變數所產生的實體都是個別獨立存在heap裡,它們所參考的記憶體位置當然是不同的,理所當然回傳false嘍! 因此要實作它…

    public class Test{

    private int x;

    public Test(int x){this.x = x;}

    public static void main(String avgs[]){

    Test t1 = new Test(5);

    Test t2 = new Test(5);

    System.out.print(t1.equals(t2));//印出true

    }

    public boolean equals(Object obj){

    if(obj instanceof Test && x == ((Test)obj).x)

    return true;

    return false;

    }

    }

    覆寫equals必須要像這樣public boolean equals(Object obj),自己定義在什麼情況下,兩物件比較才會是相等的,這裡以建構子傳入的參數值來做比較,傳入參數如果是相同的,就回傳true。

    基本型態不能使用equals(),equals()只能用在物件的比較上。

    最後,要搞清楚這樣的狀況…

    Integer i1 = 6;

    Integer i2 = 6;

    Integer i3 = new Integer(6);

    Integer i4 = new Integer(6);

    Integer i5 = 1888;

    Integer i6 = 1888;

    System.out.println(i1==i2); //true

    System.out.println(i3==i4);//false

    System.out.println(i1==i3);//false

    System.out.println(i5==i6);//false

    2009-03-20 12:01:09 補充:

    使用wrapper object直接給予基本值和new出來的,是不同道理,重點來了: java為了節省記憶體使用,它會快取介於byte、short與int,-128~127範圍的數值,boolean為true和false,char為0~0x7f(10進位為127)。

    所以i1==i2印出來會是true,因為它們介於-128~127;相反的i5==i6超出這範圍,所以印出來會是false。

    2009-03-20 12:01:14 補充:

    i3==i4 只要使用new所產生的實體,每個都是獨立的,所以當然都參考不同的記憶體位置。

    i1==i3 同樣,i1的值是放在記憶體java快取的區塊,與i3new出來的實體是不同的。

    關於,String的==與equals用法,部分是相同道理,但還是有些是不一樣的,這點在此就不做說明了,往後看書就可以了解。在學到collection後,equals()就顯得很重要。

    2009-03-21 14:50:00 補充:

    先感謝兩位前輩的指教。

    小弟想先釐清的是,既然要回答,就回答到底,沒錯,版主的問題是無須這麼大費周章,小弟也可選擇向吉他手那樣,簡單明瞭帶過,但似乎版主是剛接觸這章節,小弟只想盡心把所學都打出來,反正往後都會碰到。

    2009-03-21 15:29:06 補充:

    to GM:

    無才非資工系,相關知識相較較少,在此也請多包含,並謝謝指教。

    在此所做的覆寫equals示範也只是簡單講解,不會牽扯有關設計方面的問題,且您覆寫的equals在Car car = (Car)obj;,如果obj參考變數所指向的物件無法通過"IS-A",執行時期容易造成錯誤。

    2009-03-21 15:31:30 補充:

    引述"String中的空字串就是指向同一個位置",可以試試這段...

    String str = " ";

    String str2 = new String(" ");

    System.out.print(str == str2); //false

    其實它們是指向不同的記憶體區塊。

    2009-03-21 15:55:25 補充:

    無才雖非資工出身,但關於call by value和call by reference,Java為了避免pointer的危險性,因此使用物件皆為參考,無才也略懂。網站上有許多討論著關於call by value和call by reference,網站JavaWorld也特地為此標題整理過,在下也買了幾本書裡都有相關議題,而上述理論是看了某本知名外國作者所寫的。

    2009-03-21 16:03:08 補充:

    畢竟,版主問的只是基礎的問題,觀念上的釐清,講求簡單、能解釋觀念的示範程式碼。設計,是另一門學問,以版主的問題來說,如連範例程式碼都考慮設計進去,我想,字數應該不夠吧...

    2009-03-21 16:08:32 補充:

    to版主:

    所有物件都有繼承Object類別,都會有個equals(),而Object的equals本身內部只用了==,來做比較,所以當你使用car1.equals(car2)時,內部就是只用了car1==car2,就上述所說的,兩個new出來的是個別獨立的實體,參考到不同的記憶體位址,car1==car2當然會回傳false。

    2009-03-21 16:32:20 補充:

    在此,為了成達成我們所要的條件,當【車號相同時,兩物件必須被視為是相同】,這是我們的條件,所以在覆寫equals裡,定義【兩物件被視為相等時,所需達成的條件】,就以兩車所傳入的車號來做比較。覆寫過後,經由測試,當兩車號碼是相同時,就會回傳true,車號不同時,就為false。其實這些觀點可以先有個底,往後會再碰到,再回來反覆看過,多加練習就可以了解。

    2009-03-21 16:33:17 補充:

    再次申明,上述所說內容,不考慮【設計】的議題,只求方便解說及了解。

    2009-03-22 12:22:14 補充:

    其實在對於==與equals做解釋時,一般都是如此解釋...

    Integer i1 = new Integer(6);

    Integer i2 = new Integer(6);

    6可以說是兩Integer物件的內容值,String也是如此,在此使用車號來做比較,而【使用車號相同來達到true只是在覆寫equals()時,所要求的條件】,基本上,車號還是該物件的內容,不是嗎~

    2009-03-22 12:23:05 補充:

    感謝指教嘍~

    2009-03-23 08:40:46 補充:

    恩,無才了解覆寫equals是把【在什麼條件下,兩物件必須是相等的】,根據這個來定義,因此也只是拿出某些需要被認為是相等的資訊來做比較~也就是您說的,上例以產品的名稱來做比較。

    Source(s): 如有問題再提問
  • 吉他
    Lv 5
    1 decade ago

    "==" 用來比較物件參考是否指向同一個"物件" 與 基本型態 "值"比較

    "equals()"用來比較 物件"內容值" 是否相同

    發問者只是問兩個差別,不需要再提到什麼覆寫之類的,那些都題外話了…

    2009-03-21 12:28:22 補充:

    "==" 被用來比較兩個物件時才會與"equals()"有差別,差別就是:

    用"==" 比較兩個物件 , 比較的是物件參考是否指向同一個"物件"

    用"equals()" 比較兩個物件 , 比較的是物件"內容值"是否相同

  • 1 decade ago

    如果C++寫習慣的人去寫java, 可能會因為==而不習慣,

    以字串來說, 在c++中,

    string a = "test"; string b = "test";

    a == b是true的,

    為什麼? 因為string他有實做"多載",在你對a做==的時候, 它會去呼叫某一個method與b做比較,

    而在java中, 卻是沒有實做這個, 使得==是比較記憶體實體位置,因此你必須要使用equal, 以String這物件來說, equal就是比字串的內容, 會根據你的實做而有不同。

    而基本型態我則是認為當你做int a = 3; 與int b = 3;會是指向相同記憶體位置, 在String中的空字串就是指向同一個位置。

    在DesignPattern中, 有一個Pattern叫Flyweight, 就是透過共享技術,

    使得重複出現的東西可以用同一塊記憶體。

    2009-03-20 20:06:27 補充:

    樓下的說法有點問題喔,

    你知道call by value和call by reference的差別嗎?

    Java存在著call by value與call by reference,

    在資工的必修學科程式語言(大三課程純理論)中有清楚點出。

    Java為了避免pointer的危險性,

    因此使用物件皆為參考。

    我在寫和tuple-space有關的code,

    當要抓取tupe-space的tuple時,

    會使用一個樣本,

    而其中就會使用到equal,

    比較欄位。

    2009-03-20 20:08:19 補充:

    順便教導你一個觀念,

    對於物件之間的比較,

    千萬不要使用getXXX然後 ==,

    基於物件導向設計的information expert原則,

    你應該要把東西交給知道資訊的人做,

    不要把它拿出來搞一搞。

    2009-03-20 20:09:58 補充:

    舉一個例子,

    A會使用到B物件,

    B宣告i與j兩個實體,

    你要進行比較,

    不能使用i.getName().equal( j.getName() );

    況且這個動作不應該放於A物件中,

    它不屬於A的責任,

    因此你要把這樣的工作交給B做比較。

    既然寫了Java,

    就應該要好好思考怎樣是正確的物件導向。

    2009-03-20 20:24:05 補充:

    其實還有物件和類別的概念,

    物件和類別差在哪?

    你可以看GoF Design Pattern,

    在OO Principle那章前面有講到。

    2009-03-20 23:01:09 補充:

    to:2樓的€ Solid dream builder,能否再解釋一下,謝謝!

    那個覆寫equal的那個地方我不太懂,Car car1 = new Car(6);equal結果卻是false,是因為寫了equal的覆寫,才讓equal的結果為false嗎?

    Car car1 = new Car(6);

    Car car2 = new Car(6);

    在car1.equals(car2)會false是由於Object本身所實做的equal是看你所產生的物件實體是否相同, 若你在Car中覆寫了equal, 可以依照你喜歡做比對

    2009-03-20 23:03:38 補充:

    我舉個例子

    public class Car{

    private String m_name;

    public getName(){

    return m_name;

    }

    public boolean equals(Object obj ){

    Car car = (Car)obj;

    if( getName().equals( car.getName() ) ){

    return true;}

    return false;

    }

    };

    2009-03-20 23:05:03 補充:

    以上覆寫當你執行car1.equals(car2)時, 會去比較m_name, 如果相同才會回傳true, 但若你沒覆寫, 使用Object所實做的equal就只會看實體是否相同,

    你可以做這樣的試驗car1.equals(car1), 將會回傳True。

    2009-03-21 21:34:21 補充:

    吉他手你說的是錯的喔...

    equal你怎知道比的是內容?

    請看清楚我們所回答的內容好嗎...

    講到覆寫是必要的

    2009-03-22 20:50:08 補充:

    比較內容值是否相同是由於覆寫後去做的比較,

    但並非用於所有狀況中,

    是根據使用者之需求去決定eqaul的準則在哪,

    若是你的物件中存在的許多資訊,

    要內容全部都一樣不就比死了嗎?

    以一個例子來說,

    兩家不同廠商製造的番茄汁,

    但對於使用者來說,

    它只想知道這兩樣東西是不是都為番茄汁,

    因此只需要比較名稱即可,

    並不會比較其完整內容。

    2009-03-22 20:52:45 補充:

    又如我目前正在做的專案,

    裡面會使用到tuple-space,

    當你要抓取tuple-space的tuple時,

    會丟一個template tuple進去,

    它比較的準則為非null欄位必須相同。

    因此equal不能用比較內容來說,

    會誤導別人,

    但是依照你的範例比較內容是正確的。

Still have questions? Get your answers by asking now.