JAVA中所有類的祖先-Object類原始碼解讀
Object類是Java中所有類的祖先,在Java中每個類都是由它拓展而來,我們都知道繼承一個類的寫法
class child extends father
但是繼承Object類並不需要寫
class child extends Object
因為如果你不明確指定繼承的類,Object就被預設為是這個類的父類。
由於在Java中,每個類都是由Object類拓展而來的,所以熟悉這個類所提供的服務就有必要認真的去觀摩觀摩了。
1、Equals方法
在Objdect類中的equals方法用於檢測一個物件是否等於另外的一個物件,如果兩個物件具有相同的引用,則相等。下面用一個例子來解讀
class Employee { public Employee(String name,double salary,int year,int month,int day) { this.name = name; this.salary = salary; GregorianCalendar calendar = new GregorianCalendar(year,month-1,day); this.hireDay =calendar.getTime(); } public String getName() { return this.name; } public double getSalary() { return this.salary; } public Date getHireDay() { return this.hireDay; } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } public boolean equals(Object otherObject) { if(this==otherObject)return true; if(otherObject==null)return false; if(getClass()!=otherObject.getClass())return false; Employee other = (Employee)otherObject; return this.name.equals(other.name)&&this.salary==other.salary&&this.hireDay.equals(other.hireDay); } public int hashCode() { return 7*name.hashCode()+11*new Double(salary).hashCode()+13*hireDay.hashCode(); } /*public String toString() { return getClass().getName()+"[name="+name+",salary="+salary+",hireDay"+hireDay+"]"; }*/ private String name; private double salary; private Date hireDay; } class Manage extends Employee { public Manage(String name,double salary,int year,int month,int day) { super(name,salary,year,month,day); this.bonus = 0; } public double getSalary() { double baseSalary = super.getSalary(); return baseSalary+bonus; } public void setBonus(double b) { bonus = b; } public boolean equals(Object otherObject) { if(!super.equals(otherObject))return true; Manage other = (Manage)otherObject; return bonus == other.bonus; } public int hashCode() { return super.hashCode()+17*new Double(bonus).hashCode(); } /*public String toString() { return super.toString()+"[bonus="+bonus+"]"; }*/ private double bonus; }
這裡定義了兩個類,一個Employee類和一個子類Manage類,當我們建立兩個物件的時候
Employee alice1 = new Employee("Alice Adams",75000,1987,12,15); Employee Bob = new Employee("Bob",50000,1989,1,25); System.out.println("alice1.equals(alice3):"+alice1.equals(alice3)); System.out.println("alice1.equals(Bob):"+alice1.equals(Bob)); ... alice1.equals(alice3):true alice1.equals(Bob):false
1)可以看到輸出的結果alice1和alice指向的是同一個引用,所以結果是對的,而alice1和Bob指向的不是同一個物件,所以不相等。
2)當遇到的引數不屬於同一個類的時候equals應該怎麼做呢?比如在Employee和Manage物件中都有相同的姓名、薪水和僱傭日期。我們可以這樣定義equals
public boolean equals(Object otherObject) { if(this==otherObject)return true;//檢測this和otherObeject引用的是否同一個物件 if(otherObject==null)return false;//檢測otherObject是否為空 if(getClass()!=otherObject.getClass())return false;//比較this和otheObject是否是同一個類的 Employee other = (Employee)otherObject;//將otherObject轉換成為響應的類的型別變數 return this.name.equals(other.name)&&this.salary==other.salary&&this.hireDay.equals(other.hireDay);//開始做欄位的匹配 } //如果在子類中重新定義equals,就要在其中包含呼叫super.equals(other) public boolean equals(Object otherObject) { if(!super.equals(otherObject))return true; Manage other = (Manage)otherObject; return bonus == other.bonus; }
2、HashCode方法
HashCode是由物件匯出的一個整型值,(雜湊碼是由內容匯出的)如果x和y 是不同的物件,則他們的雜湊值一般是不同的。
在Object類中的hashCode方法預設匯出的是物件的儲存地址。
另Equals和hashCode的定義必須一致,如果x.equals(y)返回true,那麼x和y的hashCode應該具有相同的值。
System.out.println("alice1.hashCode():"+alice1.hashCode());
System.out.println("alice3.hashCode():"+alice3.hashCode());
public int hashCode()
{
return 7*name.hashCode()+11*new Double(salary).hashCode()+13*hireDay.hashCode();//與equals有同樣的欄位進行計算,計算規則自定義,但是應該讓雜湊碼更均勻
}
//輸出結果
alice1.hashCode():377780067
alice3.hashCode():377780067
//如果我們將上面的方法給註釋了,則返回的是儲存地址的值
alice1.hashCode():1028566121
alice3.hashCode():1118140819
3、toString方法***
在Object中還有一個很重要的方法就是toString方法。它用於返回表示物件值得字串。在Object中我們可以看到它是這樣定義的
/**
* Returns a string representation of the object. In general, the
* {@code toString} method returns a string that
* "textually represents" this object. The result should
* be a concise but informative representation that is easy for a
* person to read.
* It is recommended that all subclasses override this method.
* <p>
* The {@code toString} method for class {@code Object}
* returns a string consisting of the name of the class of which the
* object is an instance, the at-sign character `{@code @}', and
* the unsigned hexadecimal representation of the hash code of the
* object. In other words, this method returns a string equal to the
* value of:
* <blockquote>
* <pre>
* getClass().getName() + '@' + Integer.toHexString(hashCode())
* </pre></blockquote>
*
* @return a string representation of the object.
*/
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
alice1=alice2:[email protected],[email protected]
alice1=alice3:[email protected],[email protected]
它返回的是一個類名和雜湊碼,但是返回這個值有點太抽象,對我們的意義並不是很大,我們可以對這個方法進行過載,返回我們想要的欄位
public String toString()
{
return getClass().getName()+"[name="+name+",salary="+salary+",hireDay"+hireDay+"]";
}/**/
//輸出結果
alice1=alice2:Employee[name=Alice Adams,salary=75000.0,hireDayTue Dec 15 00:00:00 CST 1987],Employee[name=Alice Adams,salary=75000.0,hireDayTue Dec 15 00:00:00 CST 1987]
alice1=alice3:Employee[name=Alice Adams,salary=75000.0,hireDayTue Dec 15 00:00:00 CST 1987],Employee[name=Alice Adams,salary=75000.0,hireDayTue Dec 15 00:00:00 CST 1987]
對於陣列型別的域,equals、hashcode和都可以應用靜態的Arrays呼叫來檢測。
4、class getClass()
返回包含物件資訊的類的物件,
5、Object clone()
建立一個物件的副本。Java執行時系統將為新例項分配儲存控制,並不是只建立一個變數指向相同的空間哦,而是有開闢新的儲存空間。
後面的還有void notify(),voide notifyall(), void wait(long timeout) throws InterruptedException,void finalize() throws Throwable { }這幾個後面遇到再補充。。。。。