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