標籤:
我們都知道:在Java中,所有的類都繼承了Object這個基類,並且大家都知道,Object有幾個比較通用的方法,如equals(),clone(),toString(),我們需要在使用它們的時候進行覆寫,今天,我們就具體的探究下這幾個方法。
void registerNatives()
這是個Native方法,在靜態塊中調用,其目的是將hashCode,wait,notify,notifyAll和clone方法註冊到本地。
Class<?> getClass()
同樣是個Native方法,擷取對象的Class。
int hashCode()
Native方法,產生雜湊碼,其中注意三點
一個對象在同一個進程被多次調用,但是它的雜湊碼仍然應該是相同的。但是,當同一個對象在不同進程中執行,則雜湊碼有可能不同。JavaDoc原文如下
Whenever it is invoked on the same object more than once during an execution of a Java application, the {@code hashCode} method must consistently return the same integer, provided no information used in {@code equals} comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
如果兩個對象通過equals()比較返回true,那麼它們的雜湊碼應該相同。
如果兩個對象通過equals()比較返回false,那麼它們的雜湊碼應該不同。
boolean equals(Object obj)
這恐怕使我們最常用的方法之一了,我們在實際應用中,也經常遇到什麼時候用equals(),什麼時候用==的問題。一般來說,基礎資料型別 (Elementary Data Type)用==,因為這樣可以直接比較它們的值,但是複合資料型別如果我們用==的話,那麼實際上我們比較的就是它們的引用了,除非它們指向的是同一個對象,否則它們不可能相等,因此我們比較符合資料類型一般用equals(),並且我們應該覆寫equals(),這是因為Object的equals()方法預設的也是用==進行判定:
public boolean equals(Object obj) { return (this == obj); }
我們再來看看我們經常用的String是如何覆寫equals()方法的:
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false;}
在這裡還有一個很有趣的問題,請看下面的例子
String s1 = "String"; String s2 = "String"; System.out.println("The result is " + s1.equals(s2));
你會發現傳回值為True,這個就和我們上面講的不一樣了,按照我們上面的講解,這時候應該返回false才對。其實是這樣的,因為JVM中會維護一個字串池,如果池中已經有包含此對象的字串的時候,那麼它就會返回池中的字串(當然如果你new一個新的String對象的話就另當別論。)所以這個時候返回的是true。
Object clone()
Native方法,我們一般用它來複製一個對象,並且用clone()可以實現深複製(將所有需要複製的對象都複製了一遍,而不單單是用引用指向原來的對象。)樣本如下:
public class Animal implements Cloneable { private int height; private int age; public Animal(int height, int age){ this.height = height; this.age = age; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "Animal{" + "height=" + height + ", age=" + age + ‘}‘; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }}public class People implements Cloneable { private int height; private int age; private Animal a; public People(int height, int age,Animal a){ this.height = height; this.age = age; this.a = a; } @Override public Object clone() throws CloneNotSupportedException { People p = (People) super.clone(); p.a = (Animal) a.clone(); return p; } @Override public String toString() { return "People{" + "height=" + height + ", age=" + age + ", a=" + a + ‘}‘; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void setAnimalAge(int a) { this.a.setAge(5); }}
接下來我們這樣調用:
Animal a1 = new Animal(100,3); People p1 = new People(173,24,a1); People p2 = (People) p1.clone(); p2.setAge(26); p2.setHeight(181); p2.setAnimalAge(6); System.out.println(p1.toString()); System.out.println(p2.toString());
這樣我們就完成深複製了。
String toString()
最常用的方法,我們一般用它擷取對象成員變數的值。Object的預設實現:
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode());}
void notify(),void notifyAll()
Native方法,多線程時應用,通知其他線程等待結束。
void wait(long),void wait(long,int),void wait()
Native方法,通知線程等待。
void finalize()
記憶體回收。當JVM判斷一個對象可以被記憶體回收時,那麼JVM會調用finalize()方法,但是記住,它只能調用一次(所以如果你想這個對象不被垃圾清除的話,你就要在這裡面做點事情了),但是一般你不能依賴在這裡做記憶體回收的工作,在《Java編程思想》中說明了有關finalize()的一個用法,那就是通過finalize()來進行對象終結對象的判斷。
Java Object詳解