1. 程式人生 > >Java的toString方法和==和equals方法(6.2)

Java的toString方法和==和equals方法(6.2)

1 toString方法
用System.out.println§;(p為people類的物件)直接輸出物件p時,輸出了一個’類名[email protected] +hashCode值’
System.out的println()方法為什麼只能在控制檯輸出字串,而p為一個物件,怎麼能轉換為字串輸出呢?實際上輸出的是toString方法的返回值
toString方法是Object類的一個例項方法,因為所有類都是Object類的子類,所以所有類都有toString方法。toString方法返回一個字串,是用於描述物件資訊的一個方法。

//下面兩行程式碼效果完全一樣
System.out.println(p);
System.out.println(p.toString());

當直接輸出物件時,就輸出了該物件的自我描述資訊,若要返回有參考價值的資訊,需要在類中重寫該方法。

//上面定義了一個蘋果類,有 color,weight屬性
//重寫toString方法
public String toString()
{
   return "一個蘋果的顏色是" + color
      + "重量是," + weight;
}

2 ==和equals方法
Java程式中測試兩個變數是否相等有兩種方式,一種是==,一種是equals()方法
(1)

  1. 當用==來判斷兩個變數是否相等時,,如果兩個變數是基本型別,且都是數值型(不一定要求資料型別嚴格相等,比如65與65.0相等),則只要兩個變數的值相等,就返回true。
    但對於兩個引用變數,只有他們同時指向同一物件時,才會返回true,==不可用於比較型別上沒有父子關係的兩個物件

  2. String還有一個讓人迷惑的地方:“hello”直接量和new Striing(“hello”)有什麼區別?
    當使用形如“hello”的字串直接量(包括在編譯時就能計算出來的字串值)時,JVM將會使用常量池來管理這些字串;當使用new Striing(“hello”)時,JVM會先使用常量池來管理“hello”直接量,再呼叫String類的構造器來建立一個新的String物件,新建立的物件將被儲存在堆記憶體當中。換句話說,new Striing(“hello”)一共產生了兩個字串物件
    常量池(constant pool)專門用於管理在編譯時被確定並儲存在已編譯的.class檔案中的一些資料。它包含了關於類,方法,介面中的常量,還包括字串常量。JVM保證相同的直接量只有一個,不會產生多個副本。

但是在很多情況下又希望,當判斷兩個引用變數時,只要滿足類似於”值相等“的判斷規則,並不要求兩個引用變數指向同一個物件。此時就需要用到equals()方法了。

(2)
equals()方法是Object類提供的一個例項方法,因此所有引用變數都可以呼叫該方法。但Object類預設的equals()方法與==沒有任何區別,同樣要求兩個引用變數指向同一物件才會返回true。如果想實現”值相等“就返回true的規則。就需要在兩個引用變數對應的類裡重寫該方法。
注意:String類已經重寫了Object類的equals()方法,String的equals()方法的判斷規則是:只要兩個字串所包含的字串序列相同,就返回true。

class Person
{
   private String name;
   private String idStr;
   public Person(){}
   public Person(String name , String idStr)
   {
      this.name = name;
      this.idStr = idStr;
   }
   // 此處省略name和idStr的setter和getter方法   
   //重寫equals方法,提供自定義的相等標準   
   public boolean equals(Object obj)
   {
      // 如果兩個引用變數指向同一個物件      
      if (this == obj)
         return true;
      //只有當obj是Person物件時      
      if (obj != null && obj.getClass() == Person.class)
      {
         Person personObj = (Person)obj;
         // 並且當前物件的idStr與obj物件的idStr相等時才可判斷相等
         //下面程式碼利用了反射基礎
         if (this.getIdStr().equals(personObj.getIdStr()))
         {
            return true;
         }
      }
      return false;
   }
}
public class OverrideEqualsRight
{
   public static void main(String[] args)
   {
      Person p1 = new Person("孫悟空" , "12343433433");
      Person p2 = new Person("孫行者" , "12343433433");
      Person p3 = new Person("孫悟飯" , "99933433");
      // p1和p2的idStr相等,所以返回true
      System.out.println("p1和p2是否相等"
         + p1.equals(p2));
      // p2和p3的idStr相不等,所以返回false     
      System.out.println("p2和p3是否相等"
         + p2.equals(p3));
   }
}

注意:上面程式碼中判斷obj是否是person類例項不能用obj instanceof Person來判斷。因為對於 instanceof 而言,當前面對象是後面類的例項或其子類的例項都將返回true,所以重寫equals方法判斷兩個物件是否是同一個類的例項時使用 instanceof 運算子是有問題的。