作者:熔岩
日期:2007-01-16
MSN :
[email]leizhimin@126.com[/email]
宣告:原創作品,未經授權,謝絕轉載!

 

前言:Java的類庫日益龐大,所包含的類和介面也不計其數。但其中有一些非常重要的類和介面,是Java類庫中的核心部分。常見的有String、Object、Class、Collection、ClassLoader、System、Runtime…,掌握類是靈活Java這門語言的基礎。而這些類一般都很好理解和運用,需要做深入的研究和實踐才能掌握。下面是我結合實踐對這些類理解和使用的一些總結。歡迎你在閱讀後將你寶貴的意見和讀後感留下,呵呵…別忘了你也能從中賺到積分,以便能發更長的文章出來!

 

一、概述:
       Object類是所有Java類的祖先。每個類都使用 Object 作為超類。所有物件(包括陣列)都實現這個類的方法。
在不明確給出超類的情況下,Java會自動把Object作為要定義類的超類。
      可以使用型別為Object的變數指向任意型別的物件。
      Object類有一個預設構造方法pubilc Object(),在構造子類例項時,都會先呼叫這個預設構造方法。
      Object類的變數只能用作各種值的通用持有者。要對他們進行任何專門的操作,都需要知道它們的原始型別並進行型別轉換。例如:
      Object obj = new MyObject();
      MyObject x = (MyObject)obj;

 

二、API預覽
    Object()
    預設構造方法
    clone()
    建立並返回此物件的一個副本。
    equals(Object obj)
    指示某個其他物件是否與此物件“相等”。
    finalize()
    當垃圾回收器確定不存在對該物件的更多引用時,由物件的垃圾回收器呼叫此方法。
    getClass()
    返回一個物件的執行時類。
    hashCode()
    返回該物件的雜湊碼值。
    notify()
    喚醒在此物件監視器上等待的單個執行緒。
    notifyAll()
    喚醒在此物件監視器上等待的所有執行緒。
    toString()
    返回該物件的字串表示。
    wait()
    導致當前的執行緒等待,直到其他執行緒呼叫此物件的 notify() 方法或 notifyAll() 方法。
    wait(long timeout)
    導致當前的執行緒等待,直到其他執行緒呼叫此物件的 notify() 方法或 notifyAll() 方法,或者超過指定的時間量。
    wait(long timeout, int nanos)
    導致當前的執行緒等待,直到其他執行緒呼叫此物件的 notify() 方法或 notifyAll() 方法,或者其他某個執行緒中斷當前執行緒,或者已超過某個實際時間量。

 

三、方法使用說明
1、equals()方法:用於測試某個物件是否同另一個物件相等。它在Object類中的實現是判斷兩個物件是否指向同一塊記憶體區域。這中測試用處不大,因為即使內容相同的物件,記憶體區域也是不同的。如果想測試物件是否相等,就需要覆蓋此方法,進行更有意義的比較。例如
class Employee{
… //此例子來自《java核心技術》卷一
    public boolean equals(Object otherObj){
        //快速測試是否是同一個物件
        if(this == otherObj) return true;
        //如果顯式引數為null,必須返回false
        if(otherObj == null) reutrn false;
        //如果類不匹配,就不可能相等
        if(getClass() != otherObj.getClass()) return false;
       
        //現在已經知道otherObj是個非空的Employee物件
        Employee other = (Employee)otherObj;

        //測試所有的欄位是否相等
        return name.equals(other.name)
            && salary == other.salary
            && hireDay.equals(other.hireDay);
    }
}
Java語言規範要求equals方法具有下面的特點:
自反性:對於任何非空引用值 x,x.equals(x) 都應返回 true。
對稱性:對於任何非空引用值 x 和 y,當且僅當 y.equals(x) 返回 true 時,x.equals(y) 才應返回 true。
傳遞性:對於任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,並且 y.equals(z) 返回 true,那麼 x.equals(z) 應返回 true。
一致性:對於任何非空引用值 x 和 y,多次呼叫 x.equals(y) 始終返回 true 或始終返回 false,前提是物件上 equals 比較中所用的資訊沒有被修改。
對於任何非空引用值 x,x.equals(null) 都應返回 false。

從這裡看出,上面的例子是Java規範的equals方法的標準實現,推薦用上面例子的寫法實現類的equals方法。

 

2、toString():返回該物件的字串表示。Object類中的toString()方法會列印出類名和物件的記憶體位置。幾乎每個類都會覆蓋該方法,以便列印對該物件當前狀態的表示。大多數(非全部)toString()方法都遵循如下格式:類名[欄位名=值,欄位名=值…],當然,子類應該定義自己的toString()方法。例如:

public String toString(){
    reurn “Employee[name=” + name + “,salary=” + salary + “,hireDay=” + hireDay + “]”;
}
toString()方法是非常重要的除錯工具,很多標準類庫中的類都定義了toString()方法,以便程式設計師獲得有用的除錯資訊。

 

四、來自SUN公司的java.long.Object類的API文件,網上有chm中文版的,很好找。為了查閱方便,我從SUN公司的JavaDoc站點上覆製出來了Object類的API文件。

 

java.lang
類 Object

java.lang.Object

public class Object

Object 是類層次結構的根類。每個類都使用 Object 作為超類。所有物件(包括陣列)都實現這個類的方法。

從以下版本開始:
JDK1.0
另請參見:
Class


構造方法摘要
Object()
           

 

方法摘要
protected  Object clone()
          建立並返回此物件的一個副本。
 boolean equals(Object obj)
          指示某個其他物件是否與此物件“相等”。
protected  void finalize()
          當垃圾回收器確定不存在對該物件的更多引用時,由物件的垃圾回收器呼叫此方法。
 Class<? extends Object> getClass()
          返回一個物件的執行時類。
 int hashCode()
          返回該物件的雜湊碼值。
 void notify()
          喚醒在此物件監視器上等待的單個執行緒。
 void notifyAll()
          喚醒在此物件監視器上等待的所有執行緒。
 String toString()
          返回該物件的字串表示。
 void wait()
          導致當前的執行緒等待,直到其他執行緒呼叫此物件的 notify() 方法或 notifyAll() 方法。
 void wait(long timeout)
          導致當前的執行緒等待,直到其他執行緒呼叫此物件的 notify() 方法或 notifyAll() 方法,或者超過指定的時間量。
 void wait(long timeout, int nanos)
          導致當前的執行緒等待,直到其他執行緒呼叫此物件的 notify() 方法或 notifyAll() 方法,或者其他某個執行緒中斷當前執行緒,或者已超過某個實際時間量。

 

構造方法詳細資訊

Object

public Object()

方法詳細資訊

getClass

public final Class<? extends Object> getClass()
返回一個物件的執行時類。該 Class 物件是由所表示類的 static synchronized 方法鎖定的物件。

返回:
表示該物件的執行時類的 java.lang.Class 物件。此結果屬於型別 Class<? extends X>,其中 X 表示清除表示式中的靜態型別,該表示式呼叫 getClass

hashCode

public int hashCode()
返回該物件的雜湊碼值。支援該方法是為雜湊表提供一些優點,例如,java.util.Hashtable 提供的雜湊表。

hashCode 的常規協定是:

  • 在 Java 應用程式執行期間,在同一物件上多次呼叫 hashCode 方法時,必須一致地返回相同的整數,前提是物件上 equals 比較中所用的資訊沒有被修改。從某一應用程式的一次執行到同一應用程式的另一次執行,該整數無需保持一致。
  • 如果根據 equals(Object) 方法,兩個物件是相等的,那麼在兩個物件中的每個物件上呼叫 hashCode 方法都必須生成相同的整數結果。
  • 以下情況 是必需的:如果根據 equals(java.lang.Object) 方法,兩個物件不相等,那麼在兩個物件中的任一物件上呼叫 hashCode 方法必定會生成不同的整數結果。但是,程式設計師應該知道,為不相等的物件生成不同整數結果可以提高雜湊表的效能。

實際上,由 Object 類定義的 hashCode 方法確實會針對不同的物件返回不同的整數。(這一般是通過將該物件的內部地址轉換成一個整數來實現的,但是 JavaTM 程式語言不需要這種實現技巧。)

返回:
此物件的一個雜湊碼值。
另請參見:
equals(java.lang.Object), Hashtable


equals

public boolean equals(Object obj)
指示某個其他物件是否與此物件“相等”。

equals 方法在非空物件引用上實現相等關係:

  • 自反性:對於任何非空引用值 xx.equals(x) 都應返回 true
  • 對稱性:對於任何非空引用值 xy,當且僅當 y.equals(x) 返回 true 時,x.equals(y) 才應返回 true
  • 傳遞性:對於任何非空引用值 xyz,如果 x.equals(y) 返回 true,並且 y.equals(z) 返回 true,那麼 x.equals(z) 應返回 true
  • 一致性:對於任何非空引用值 xy,多次呼叫 x.equals(y) 始終返回 true 或始終返回 false,前提是物件上 equals 比較中所用的資訊沒有被修改。
  • 對於任何非空引用值 xx.equals(null) 都應返回 false

Object 類的 equals 方法實現物件上差別可能性最大的相等關係;即,對於任何非空引用值 xy,當且僅當 xy 引用同一個物件時,此方法才返回 truex == y 具有值 true)。

注意:當此方法被重寫時,通常有必要重寫 hashCode 方法,以維護 hashCode 方法的常規協定,該協定宣告相等物件必須具有相等的雜湊碼。

引數:
obj – 要與之比較的引用物件。
返回:
如果此物件與 obj 引數相同,則返回 true;否則返回 false
另請參見:
hashCode(), Hashtable


clone

protected Object clone()
                throws CloneNotSupportedException
建立並返回此物件的一個副本。“副本”的準確含義可能依賴於物件的類。一般來說,對於任何物件 x,如果表示式:
x.clone() != x

是正確的,則表示式:

x.clone().getClass() == x.getClass()

將為 true,但這些不是絕對條件。一般情況下是:

x.clone().equals(x)

將為 true,但這不是絕對條件。

按照慣例,返回的物件應該通過呼叫 super.clone 獲得。如果一個類及其所有的超類(Object 除外)都遵守此約定,則 x.clone().getClass() == x.getClass()

按照慣例,此方法返回的物件應該獨立於該物件(正被克隆的物件)。要獲得此獨立性,在 super.clone 返回物件之前,有必要對該物件的一個或多個欄位進行修改。這通常意味著要複製包含正在被克隆物件的內部“深層結構”的所有可變物件,並使用對副本的引用替換對這些物件的引用。如果一個類只包含基本欄位或對不變物件的引用,那麼通常不需要修改 super.clone 返回的物件中的欄位。

Object 類的 clone 方法執行特定的克隆操作。首先,如果此物件的類不能實現介面 Cloneable,則會丟擲 CloneNotSupportedException。注意:所有的陣列都被視為實現介面 Cloneable。否則,此方法會建立此物件的類的一個新例項,並像通過分配那樣,嚴格使用此物件相應欄位的內容初始化該物件的所有欄位;這些欄位的內容沒有被自我克隆。所以,此方法執行的是該物件的“淺表複製”,而不“深層複製”操作。

Object 類本身不實現介面 Cloneable,所以在類為 Object 的物件上呼叫 clone 方法將會導致在執行時丟擲異常。

返回:
此例項的一個克隆。
丟擲:
CloneNotSupportedException – 如果物件的類不支援 Cloneable 介面,則重寫 clone 方法的子類也會丟擲此異常,以指示無法克隆某個例項。
另請參見:
Cloneable


toString

public String toString()
返回該物件的字串表示。通常,toString 方法會返回一個“以文字方式表示”此物件的字串。結果應是一個簡明但易於讀懂。建議所有子類都重寫此方法。

Object 類的 toString 方法返回一個字串,該字串由類名(物件是該類的一個例項)、at 標記符“@”和此物件雜湊碼的無符號十六進位制表示組成。換句話說,該方法返回一個字串,它的值等於:

getClass().getName() + `@` + Integer.toHexString(hashCode())
 

返回:
該物件的字串表示形式。

notify

public final void notify()
喚醒在此物件監視器上等待的單個執行緒。如果所有執行緒都在此物件上等待,則會選擇喚醒其中一個執行緒。選擇是任意性的,並在對實現做出決定時發生。執行緒通過呼叫其中一個 wait 方法,在物件的監視器上等待。

直到當前的執行緒放棄此物件上的鎖定,才能繼續執行被喚醒的執行緒。被喚醒的執行緒將以常規方式與在該物件上主動同步的其他所有執行緒進行競爭;例如,喚醒的執行緒在作為鎖定此物件的下一個執行緒方面沒有可靠的特權或劣勢。

此方法只應由作為此物件監視器的所有者的執行緒來呼叫。通過以下三種方法之一,執行緒可以成為此物件監視器的所有者:

  • 通過執行此物件的同步 (Sychronized) 例項方法。
  • 通過執行在此物件上進行同步的 synchronized 語句的正文。
  • 對於 Class 型別的物件,可以通過執行該類的同步靜態方法。

一次只能有一個執行緒擁有物件的監視器。

丟擲:
IllegalMonitorStateException – 如果當前的執行緒不是此物件監視器的所有者。
另請參見:
notifyAll(), wait()


notifyAll

public final void notifyAll()
喚醒在此物件監視器上等待的所有執行緒。執行緒通過呼叫其中一個 wait 方法,在物件的監視器上等待。

直到當前的執行緒放棄此物件上的鎖定,才能繼續執行被喚醒的執行緒。被喚醒的執行緒將以常規方式與在該物件上主動同步的其他所有執行緒進行競爭;例如,喚醒的執行緒在作為鎖定此物件的下一個執行緒方面沒有可靠的特權或劣勢。

此方法只應由作為此物件監視器的所有者的執行緒來呼叫。請參閱 notify 方法,瞭解執行緒能夠成為監視器所有者的方法的描述。

丟擲:
IllegalMonitorStateException – 如果當前的執行緒不是此物件監視器的所有者。
另請參見:
notify(), wait()


wait

public final void wait(long timeout)
                throws InterruptedException
導致當前的執行緒等待,直到其他執行緒呼叫此物件的 notify() 方法或 notifyAll() 方法,或者超過指定的時間量。

當前的執行緒必須擁有此物件監視器。

此方法導致當前執行緒(稱之為 T)將其自身放置在物件的等待集中,然後放棄此物件上的所有同步要求。出於執行緒排程目的,執行緒 T 被禁用,且處於休眠狀態,直到發生以下四種情況之一:

  • 其他某個執行緒呼叫此物件的 notify 方法,並且執行緒 T 碰巧被任選為被喚醒的執行緒。
  • 其他某個執行緒呼叫此物件的 notifyAll 方法。
  • 其他某個執行緒中斷執行緒 T
  • 已經到達指定的實際時間。但是,如果 timeout 為零,則不考慮實際時間,該執行緒將一直等待,直到獲得通知。

然後,從物件的等待集中刪除執行緒 T,並重新進行執行緒排程。然後,該執行緒以常規方式與其他執行緒競爭,以獲得在該物件上同步的權利;一旦獲得對該物件的控制權,該物件上的所有其同步宣告都將被還原到以前的狀態 – 這就是呼叫 wait 方法時的情況。然後,執行緒 Twait 方法的呼叫中返回。所以,從 wait 方法返回時,該物件和執行緒 T 的同步狀態與呼叫 wait 方法時的情況完全相同。

在沒有被通知、中斷或超時的情況下,執行緒還可以喚醒一個所謂的虛假喚醒 (spurious wakeup)。雖然這種情況在實踐中很少發生,但是應用程式必須通過以下方式防止其發生,即對應該導致該執行緒被提醒的條件進行測試,如果不滿足該條件,則繼續等待。換句話說,等待應總是發生在迴圈中,如下面的示例:

synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
     }
 

(有關這一主題的更多資訊,請參閱 Doug Lea 撰寫的《Concurrent Programming in Java (Second Edition)》(Addison-Wesley, 2000) 中的第 3.2.3 節或 Joshua Bloch 撰寫的《Effective Java Programming Language Guide》(Addison-Wesley, 2001) 中的第 50 項。

如果當前執行緒在等待時被其他執行緒中斷,則會丟擲 InterruptedException。在按上述形式恢復此物件的鎖定狀態時才會丟擲此異常。

注意,由於 wait 方法將當前的執行緒放入了物件的等待集中,所以它只能解除此物件的鎖定;可以同步當前執行緒的任何其他物件線上程等待時仍處於鎖定狀態。

此方法只應由作為此物件監視器的所有者的執行緒來呼叫。請參閱 notify 方法,瞭解執行緒能夠成為監視器所有者的方法的描述。

引數:
timeout – 要等待的最長時間(以毫秒為單位)。
丟擲:
IllegalArgumentException – 如果超時值為負。
IllegalMonitorStateException – 如果當前的執行緒不是此物件監視器的所有者。
InterruptedException – 如果在當前執行緒等待通知之前或者正在等待通知時,另一個執行緒中斷了當前執行緒。在丟擲此異常時,當前執行緒的中斷狀態 被清除。
另請參見:
notify(), notifyAll()


wait

public final void wait(long timeout,
                       int nanos)
                throws InterruptedException
導致當前的執行緒等待,直到其他執行緒呼叫此物件的 notify() 方法或 notifyAll() 方法,或者其他某個執行緒中斷當前執行緒,或者已超過某個實際時間量。

此方法類似於一個引數的 wait 方法,但它允許更好地控制在放棄之前等待通知的時間量。用毫微秒度量的實際時間量可以通過以下公式計算出來:

1000000*timeout+nanos

在其他所有方面,此方法執行的操作與帶有一個引數的 wait(long) 方法相同。需要特別指出的是,wait(0, 0)wait(0) 相同。

當前的執行緒必須擁有此物件監視器。該執行緒釋出對此監視器的所有權,並等待下面兩個條件之一發生:

  • 其他執行緒通過呼叫 notify 方法,或 notifyAll 方法通知在此物件的監視器上等待的執行緒醒來。
  • timeout 毫秒值與 nanos 毫微秒引數值之和指定的超時時間已用完。

然後,該執行緒等到重新獲得對監視器的所有權後才能繼續執行。

對於某一個引數的版本,實現中斷和虛假喚醒是有可能的,並且此方法應始終在迴圈中使用:

synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout, nanos);
... // Perform action appropriate to condition
     }
 

此方法只應由作為此物件監視器的所有者的執行緒來呼叫。請參閱 notify 方法,瞭解執行緒能夠成為監視器所有者的方法的描述。

引數:
timeout – 要等待的最長時間(以毫秒為單位)。
nanos – 額外時間(以毫微秒為單位,範圍是 0-999999)。
丟擲:
IllegalArgumentException – 如果超時值是負數,或者毫微秒值不在 0-999999 範圍內。
IllegalMonitorStateException – 如果當前執行緒不是此物件監視器的所有者。
InterruptedException – 如果在當前執行緒等待通知之前或者正在等待通知時,其他執行緒中斷了當前執行緒。在丟擲此異常時,當前執行緒的中斷狀態 被清除。

wait

public final void wait()
                throws InterruptedException
導致當前的執行緒等待,直到其他執行緒呼叫此物件的 notify() 方法或 notifyAll() 方法。換句話說,此方法的行為就好像它僅執行 wait(0) 呼叫一樣。

當前的執行緒必須擁有此物件監視器。該執行緒釋出對此監視器的所有權並等待,直到其他執行緒通過呼叫 notify 方法,或 notifyAll 方法通知在此物件的監視器上等待的執行緒醒來。然後該執行緒將等到重新獲得對監視器的所有權後才能繼續執行。

對於某一個引數的版本,實現中斷和虛假喚醒是可能的,而且此方法應始終在迴圈中使用:

synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
     }
 

此方法只應由作為此物件監視器的所有者的執行緒來呼叫。請參閱 notify 方法,瞭解執行緒能夠成為監視器所有者的方法的描述。

丟擲:
IllegalMonitorStateException – 如果當前的執行緒不是此物件監視器的所有者。
InterruptedException – 如果在當前執行緒等待通知之前或者正在等待通知時,另一個執行緒中斷了當前執行緒。在丟擲此異常時,當前執行緒的中斷狀態 被清除。
另請參見:
notify(), notifyAll()


finalize

protected void finalize()
                 throws Throwable
當垃圾回收器確定不存在對該物件的更多引用時,由物件的垃圾回收器呼叫此方法。子類重寫 finalize 方法,以配置系統資源或執行其他清除。

finalize 的常規協定是:當 JavaTM 虛擬機器已確定尚未終止的任何執行緒無法再通過任何方法訪問此物件時,將呼叫此方法,除非由於準備終止的其他某個物件或類的終結操作執行了某個操作。finalize 方法可以採取任何操作,其中包括再次使此物件對其他執行緒可用;不過,finalize 的主要目的是在不可撤消地丟棄物件之前執行清除操作。例如,表示輸入/輸出連線的物件的 finalize 方法可執行顯式 I/O 事務,以便在永久丟棄物件之前中斷連線。

Object 類的 finalize 方法執行非特殊性操作;它僅執行一些常規返回。Object 的子類可以重寫此定義。

Java 程式語言不保證哪個執行緒將呼叫某個給定物件的 finalize 方法。但可以保證在呼叫 finalize 時,呼叫 finalize 的執行緒將不會持有任何使用者可見的同步鎖定。如果 finalize 方法丟擲未捕獲的異常,那麼該異常將被忽略,並且該物件的終結操作將終止。

在啟用某個物件的 finalize 方法後,將不會執行進一步操作,直到 Java 虛擬機器再次確定尚未終止的任何執行緒無法再通過任何方法訪問此物件,其中包括由準備終止的其他物件或類執行的可能操作,在執行該操作時,物件可能被丟棄。

對於任何給定物件,Java 虛擬機器最多隻呼叫一次 finalize 方法。

finalize 方法丟擲的任何異常都會導致此物件的終結操作停止,但可以通過其他方法忽略它。

丟擲:
Throwable – 此方法丟擲的 Exception