1. 程式人生 > >JAVA中所有類的祖先-Object類原始碼解讀

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 { }這幾個後面遇到再補充。。。。。