Class Overview(類概述)
這個(gè)類是 Java 類等級(jí)中的根。所有非初級(jí)的類型(包括數(shù)組)都是直接或間接繼承這個(gè)類。
按照以下這種風(fēng)格寫一個(gè)規(guī)范的 <span id="equals">equals</span> 方法:
// Use @Override to avoid accidental overloading.
// 使用@Override 為了避免意外的過(guò)載
@Override public boolean equals(Object o) {
// Return true if the objects are identical.
// (This is just an optimization, not required for correctness.)
// 如果對(duì)象是相同的就返回 true
// (這僅僅是一種優(yōu)化,并不要求正確性。)
if (this == o) {
return true;
}
// Return false if the other object has the wrong type.
// This type may be an interface depending on the interface's specification.
// 如果另一個(gè)對(duì)象的類型有誤,則返回 false
// 這種類型可能是一個(gè)接口,取決于接口的規(guī)格
if (!(o instanceof MyType)) {
return false;
}
// Cast to the appropriate type.
// This will succeed because of the instanceof, and lets us access private fields.
// 轉(zhuǎn)換成適當(dāng)?shù)念愋? // 這將是成功的因?yàn)?o 是 Mytype 的實(shí)例,我們?cè)L問(wèn)私有字段
MyType lhs = (MyType) o;
// Check each field. Primitive fields, reference fields, and nullable reference
// fields are all treated differently.
// 檢查每一個(gè)字段。原始的字段,參考的字段,空引用的字段都被看成是不同的。
return primitiveField == lhs.primitiveField &&
referenceField.equals(lhs.referenceField) &&
(nullableField == null ? lhs.nullableField == null
: nullableField.equals(lhs.nullableField));
}
如果要重寫 equals 方法,同時(shí)也應(yīng)該重寫 hashCode 方法:相同的實(shí)例必須要有相同的哈希值。
參考 Effcetive Java 里的第 8 條,有更詳細(xì)的說(shuō)明。
按照以下這種風(fēng)格寫一人規(guī)范的 <span id="hash" >hashCode</span> 方法:
@Override public int hashCode() {
// Start with a non-zero constant.
// 開始于一個(gè)非零常數(shù)
int result = 17;
// Include a hash for each field.
// 包括每一個(gè)字段的哈希值
result = 31 * result + (booleanField ? 1 : 0);
result = 31 * result + byteField;
result = 31 * result + charField;
result = 31 * result + shortField;
result = 31 * result + intField;
result = 31 * result + (int) (longField ^ (longField >>> 32));
result = 31 * result + Float.floatToIntBits(floatField);
long doubleFieldBits = Double.doubleToLongBits(doubleField);
result = 31 * result + (int) (doubleFieldBits ^ (doubleFieldBits >>> 32));
result = 31 * result + Arrays.hashCode(arrayField);
result = 31 * result + referenceField.hashCode();
result = 31 * result +
(nullableReferenceField == null ? 0
: nullableReferenceField.hashCode());
return result;
}
如果不打算將您的類型用作哈希鍵, 也不要只依賴于默認(rèn)的 hashCode 方法實(shí)現(xiàn)。因?yàn)檫@樣會(huì)不明顯的破壞將來(lái)任何一個(gè)把該類型做為哈希鍵的編碼。應(yīng)該用拋異常的方法來(lái)替代:
@Override public int hashCode() {
throw new UnsupportedOperationException();
}
參考 Effective Java 第 9 條,有更詳細(xì)的說(shuō)明。
為了調(diào)試方便,按照以下的風(fēng)格重寫 <span id="toString"> toString </span>是很常見的:
@Override public String toString() {
return getClass().getName() + "[" +
"primitiveField=" + primitiveField + ", " +
"referenceField=" + referenceField + ", " +
"arrayField=" + Arrays.toString(arrayField) + "]";
}
包含的字段集一般與用 equals 方法測(cè)試的字段是一樣的。
參考 Effective Java 第 10 條,有更詳細(xì)的說(shuō)明。
Public Constructors(公共構(gòu)造方法)
public Object()
構(gòu)造一個(gè)新的 Object 實(shí)例。
Public Methods(公共方法)
<span id="eq">public boolean equals(Object o)</span>
比較該實(shí)例與指定的對(duì)象,并且指示它們是否相同。為了相同,o 必須使用特定的類比較來(lái)表示與此實(shí)例相同的對(duì)象。
通用約定是,這種比較應(yīng)該是自反性,對(duì)稱性,傳遞性。除了 null,沒(méi)有引用的對(duì)象等于 null。
僅僅當(dāng) this==o 的時(shí)候默認(rèn)返回 true。如果想要實(shí)現(xiàn)自己的 equals 方法,參考寫一個(gè)正確的 equals 方法。
對(duì)于 equals 方法和 hashCode 方法來(lái)說(shuō),通用約定是,如果兩個(gè)對(duì)象根據(jù) equals 方法比較是相等的,那么調(diào)用這兩個(gè)對(duì)象中任意一個(gè)對(duì)象的 hashCode 方法都必須產(chǎn)生同樣的整數(shù)結(jié)果。這就意味著,Object 的任意一個(gè)子類通常這兩個(gè)方法都會(huì)復(fù)寫,或者都不復(fù)寫。
參數(shù)
o 與該實(shí)例比較的對(duì)象。
返回值
如果指定的對(duì)象與該對(duì)象相同,返回 true ,否則返回 false。
參考
public final Class<?> getClass()
返回一個(gè)唯一的 Class 實(shí)例,表示這個(gè)對(duì)象的類。注意,getClass()是一個(gè)特例,它事實(shí)上返回Class ,Foo 是對(duì)表達(dá)式類型的擦除當(dāng) getClass()被調(diào)用時(shí)(這里我也不懂,實(shí)在不知道該怎么翻譯 > .. <)。
正如這個(gè)例子,下面的代碼實(shí)際上是會(huì)可以編譯的,雖然有人認(rèn)為可能不會(huì):
List l = new ArrayList();
Class c = l.getClass();
返回值
該對(duì)象類的實(shí)例。
<sapn id="hashcode">public int hashCode()</span>
返回一個(gè)該對(duì)象的 hash code,根據(jù)約定,如果兩個(gè)對(duì)象通過(guò) equals 方法返回 true,那么這兩個(gè)對(duì)象一定會(huì)返回相同的 hash code 值。這就意味著 Object 的所有子類都會(huì)同時(shí)復(fù)寫這兩個(gè)方法或是一個(gè)全都不復(fù)寫。
注意,除非用 euqals 比較的信息改變,否則 hash 的值是不會(huì)變的。
如果想要實(shí)現(xiàn)自己的 hashCode 方法,參考寫一個(gè)正確的 hashCode 方法.
返回值
該對(duì)象的 hash code。
參考
public final void notify()
由于一個(gè)正在等待該對(duì)象的監(jiān)聽器的(通過(guò)調(diào)用 wait() 方法)線程被喚醒。如果正在等待的線程多于一個(gè),VM 會(huì)任意選擇它們中的一個(gè)。被選擇的這個(gè)線程不會(huì)馬上執(zhí)行。該線程調(diào)用 notify() 方法先釋放該對(duì)象的監(jiān)聽器。而且,所選的線程仍要與試圖同步在同一對(duì)象上的其他線程競(jìng)爭(zhēng)。
這個(gè)方法只能由該對(duì)象監(jiān)聽器的線程調(diào)用。線程成為該對(duì)象監(jiān)聽器的所有者
- 通過(guò)執(zhí)行該對(duì)象的同步方法;
- 通過(guò)執(zhí)行同步對(duì)象的同步語(yǔ)句的正文;
- 如果對(duì)象類型為Class,則通過(guò)執(zhí)行同步靜態(tài)方法。
參考
notify()
wait()
wait(long)
wait(long,int)
Thread
public final void notifyAll()
由于所有正在等待該對(duì)象的監(jiān)聽器的(通過(guò)調(diào)用 wait() 方法)線程被喚醒。這些線程不會(huì)馬上執(zhí)行。線程調(diào)用 notify() 方法先釋放該對(duì)象的監(jiān)聽器。而且,這些線程仍要與試圖同步在同一對(duì)象上的其他線程競(jìng)爭(zhēng)。
這個(gè)方法只能由該對(duì)象監(jiān)聽器的線程調(diào)用。線程成為該對(duì)象監(jiān)聽器的所有者
- 通過(guò)執(zhí)行該對(duì)象的同步方法;
- 通過(guò)執(zhí)行同步對(duì)象的同步語(yǔ)句的正文;
- 如果對(duì)象類型為Class,則通過(guò)執(zhí)行同步靜態(tài)方法。
異常
IllegalMonitorStateException(非法監(jiān)視狀態(tài)異常) 當(dāng)調(diào)用該方法的線程不是該對(duì)象監(jiān)聽器的所有者。
參考
notify()
wait()
wait(long)
wait(long,int)
public String toString()
返回一個(gè)簡(jiǎn)潔的,人類可讀的描述該對(duì)象的字符串。建議子類復(fù)寫這個(gè)方法,并且提供一個(gè)考慮到該對(duì)象的類型和數(shù)據(jù)的實(shí)現(xiàn)。默認(rèn)的實(shí)現(xiàn)相當(dāng)于以下的表達(dá)形式:
getClass().getName() + '@' + Integer.toHexString(hashCode())
如果想要實(shí)現(xiàn)一個(gè)自己的 toString 方法,參見寫一個(gè)正確的 toString 方法。
返回值
該對(duì)象的一個(gè)可打印的表達(dá)形式。
public final void wait()
由于調(diào)用線程時(shí)要等到另一個(gè)線程調(diào)用了該對(duì)象的 notify() 或 notifyAll() 方法。該方法只能由該對(duì)象的監(jiān)聽器的線程調(diào)用,參見 notify() 中如何使一個(gè)線程成為監(jiān)聽器的所有者。
一個(gè)正在等待的線程可能會(huì)由于接受到 interrupt() 而導(dǎo)致提前停止等待,所以 wait 方法應(yīng)該循環(huán)調(diào)用,以檢查在繼續(xù)之前已經(jīng)等待的條件是否已滿足。
當(dāng)線程在等待的時(shí)候,它會(huì)放棄對(duì)該對(duì)象的監(jiān)聽器的所有權(quán)。當(dāng)它被通知(或是被中斷)時(shí),在開始運(yùn)行之前它會(huì)重新獲得監(jiān)聽器。
異常
IlleaglMonitorStateException (非法監(jiān)視狀態(tài)異常) 當(dāng)調(diào)用該方法的線程不是該對(duì)象的監(jiān)聽所有者。
InterruptedException (中斷異常) 如果當(dāng)前線程已經(jīng)被中斷。在異常拋出之前,當(dāng)前線程的中斷狀態(tài)會(huì)被清除。
參考
notify()
notifyAll()
wait(long)
wait(long,int)
Thread
public final void wait(long millis,int nanos)
由于調(diào)用線程時(shí)要等到另一個(gè)線程調(diào)用了該對(duì)象的 notify() 或 notifyAll() 方法,或是過(guò)了指定的超時(shí)時(shí)間。該方法只由該對(duì)象的監(jiān)聽器的線程調(diào)用,參見 notify() 中如何使一個(gè)線程成為監(jiān)聽器的所有者。
一個(gè)正在等待的線程可能會(huì)由于接受到 interrupt() 而導(dǎo)致提前停止等待,所以 wait 方法應(yīng)該循環(huán)調(diào)用,以檢查在繼續(xù)之前已經(jīng)等待的條件是否已滿足。
當(dāng)線程在等待的時(shí)候,它會(huì)放棄對(duì)該對(duì)象的監(jiān)聽器的所有權(quán)。當(dāng)它被通知(或是被中斷)時(shí),在開始運(yùn)行之前它會(huì)重新獲得監(jiān)聽器。
當(dāng)超時(shí)時(shí)間為 0 時(shí),表示正在調(diào)用的線程應(yīng)該一直等待,除非被中斷或是被通知。
參數(shù)
millis 等待的最大時(shí)間,以毫秒為單位。
nanos 等待的毫秒數(shù),以納少為單位。
異常
IllegalArgumentException (非法參數(shù)異常) 當(dāng) millis < 0,nanos < 0 或 nanos > 999999.
IllegalMonitorStateException (非法監(jiān)視狀態(tài)異常) 當(dāng)調(diào)用該方法的線程不是該對(duì)象的監(jiān)聽所有者。
InterruptedException (中斷異常) 如果當(dāng)前線程已經(jīng)被中斷。在異常拋出之前,當(dāng)前線程的中斷狀態(tài)會(huì)被清除。
參考
notify()
notifyAll()
wait(long)
wait(long,int)
Thread
public final void wait(long millis)
由于調(diào)用線程時(shí)要等到另一個(gè)線程調(diào)用了該對(duì)象的 notify() 或 notifyAll() 方法,或是過(guò)了指定的超時(shí)時(shí)間。該方法只由該對(duì)象的監(jiān)聽器的線程調(diào)用,參見 notify() 中如何使一個(gè)線程成為監(jiān)聽器的所有者。
一個(gè)正在等待的線程可能會(huì)由于接受到 interrupt() 而導(dǎo)致提前停止等待,所以 wait 方法應(yīng)該循環(huán)調(diào)用,以檢查在繼續(xù)之前已經(jīng)等待的條件是否已滿足。
當(dāng)線程在等待的時(shí)候,它會(huì)放棄對(duì)該對(duì)象的監(jiān)聽器的所有權(quán)。當(dāng)它被通知(或是被中斷)時(shí),在開始運(yùn)行之前它會(huì)重新獲得監(jiān)聽器。
當(dāng)超時(shí)時(shí)間為 0 時(shí),表示正在調(diào)用的線程應(yīng)該一直等待,除非被中斷或是被通知。
參數(shù)
millis 等待的最大時(shí)間,以毫秒為單位。
異常
IllegalArgumentException (非法參數(shù)異常) 當(dāng) millis < 0,nanos < 0 或 nanos > 999999.
IllegalMonitorStateException (非法監(jiān)視狀態(tài)異常) 當(dāng)調(diào)用該方法的線程不是該對(duì)象的監(jiān)聽所有者。
InterruptedException (中斷異常) 如果當(dāng)前線程已經(jīng)被中斷。在異常拋出之前,當(dāng)前線程的中斷狀態(tài)會(huì)被清除。
參考
notify()
notifyAll()
wait(long)
wait(long,int)
Thread
Protected Methods(被保護(hù)的方法)
protected Object clone()
創(chuàng)造并返回該對(duì)象的一個(gè)副本。默認(rèn)的實(shí)現(xiàn)返回一個(gè)所謂的淺的("shallow")的副本:它創(chuàng)建一個(gè)同類的新的實(shí)例,然后從該實(shí)例復(fù)制字段值(包括對(duì)象的引用)到新的實(shí)例。相反,“深”副本(deep)還會(huì)遞歸地克隆嵌套對(duì)象。需要實(shí)現(xiàn)這種克隆的子類應(yīng)該調(diào)用 super.clone()來(lái)創(chuàng)建新的實(shí)例,然后創(chuàng)建嵌套的可變對(duì)象的深層副本。
返回值
該對(duì)象的副本。
異常
CloneNotSupportedException (克隆不支持異常) 如果該對(duì)象的類不能實(shí)現(xiàn) Cloneable 接口。
protected void finalize()
當(dāng)垃圾收集器檢測(cè)到該實(shí)例不再是可獲得的時(shí)調(diào)用。默認(rèn)不做任何操作,但為了釋放資源該方法可以被復(fù)寫。
注意,重寫該方法的對(duì)象比不重寫更消耗資源。當(dāng)該對(duì)象是不可獲得的之后的終結(jié)器可能還會(huì)運(yùn)行一段時(shí)間,這個(gè)由內(nèi)存的壓力決定,所以通過(guò)它們進(jìn)行清理不是好的做法。另外,終結(jié)器運(yùn)行在單個(gè)VM范圍的終結(jié)器線程上,因此在終結(jié)器中時(shí)行模塊化工作不是好的做法。終結(jié)器通常只需要有一個(gè)類,那個(gè)類有一個(gè)本地對(duì)等全,并且需要調(diào)用一個(gè)本地的方法去銷毀本地對(duì)等體。即便這樣,提供一個(gè)明確的關(guān)閉方法(并實(shí)現(xiàn) Closeable 接口)是好的做法,并且堅(jiān)持通過(guò)手動(dòng)調(diào)用處理實(shí)例。這對(duì)于像文件這樣的東西效果很好,但對(duì)于像 BigInteger 這樣的東西來(lái)說(shuō),不是很好,那些典型的調(diào)用代碼必須處理大量的臨時(shí)文件。不幸的是,從單個(gè)終結(jié)器線程的角度來(lái)看,創(chuàng)建大量臨時(shí)文件的代碼是最差的代碼。
如果必須使用終結(jié)器,要考慮至少提供一個(gè)自己的 ReferenceQueue 并且有自己的線程來(lái)處理這個(gè) queue。
與構(gòu)造函數(shù)不一樣,終結(jié)器沒(méi)有自動(dòng)鏈接。需要自己調(diào)用 super.finalize()。
由終結(jié)器拋出的未捕獲的異常被忽略,不終止終結(jié)器的線程。參考 Effective Java 第 7 條,有更詳細(xì)的說(shuō)明。
異常
Throwable