Object
1. @HotSpotIntrinsicCandidate
@HotSpotIntrinsicCandidate
public final native Class<?> getClass();
使用@HotSpotIntrinsicCandidate
註解標註的方法,表示JVM可能為該方法提供了一些基於CPU指令的高效實現,而非使用Java的實現。
2. native方法
getClass()
、hashCode()
、clone()
、notify()
等方法的預設實現都是native方法
3. equals方法
equals()
方法預設實現
public boolean equals(Object obj) {
return (this == obj);
}
4. clone方法
clone()
方法預設是native實現,且預設是一個淺拷貝。但要呼叫這個方法,要求類實現Clonable
介面,否則會丟擲CloneNotSupportedException
異常。即使Clonable
沒有定義任何方法。
public interface Cloneable {
}
下面是一個簡單的示例
public class Test implements Cloneable{
public int a = 10;
public static void main(String[] args) {
try {
Test test = new Test();
Object clone = test.clone();
System.out.println(clone.getClass());
System.out.println(test.getClass());
System.out.println(test.a);
Test toClone = (Test)clone;
System.out.println(toClone.a);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
// 輸出
class Test
class Test
10
10
6. toString方法
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
預設實現返回類名+十六進位制雜湊碼
7. notify和notifyAll方法
喚醒在物件監視器上等待的執行緒。
有下面這些方法令當前執行緒獲得一個物件的監視器
- 執行synchronized方法
- 執行synchronized塊
- 執行synchronized的靜態方法(獲得的是當前類的class物件的監視器)
8. wait方法
下面是一個帶納秒引數nano
的wait方法
public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
if (timeoutMillis < 0) {
throw new IllegalArgumentException("timeoutMillis value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
timeoutMillis++;
}
wait(timeoutMillis);
}
我們看到第三個if判斷,假如nano引數大於0且timeoutMillis引數未滿,所做的直接是令timeoutMillis引數自增。最後直接呼叫wait(timeoutMillis)
,這簡直是對程式設計師的欺騙。注:1ms = 1000000ms
下面的這段程式碼是一段示例程式碼。推薦的等待方法是在呼叫wait的while迴圈中檢查等待的條件,如下例所示。 這種方法避免了可能由虛假喚醒引起的問題。
虛假喚醒:執行緒可以在沒有被通知、中斷或超時的情況下喚醒
synchronized (obj) {
while (<condition does not hold> and <timeout not exceeded>) {
long timeoutMillis = ... ; // recompute timeout values
int nanos = ... ;
obj.wait(timeoutMillis, nanos);
}
... // Perform action appropriate to condition or timeout
}
9. finalize方法
@Deprecated(since="9")
protected void finalize() throws Throwable { }
顯然我們看到,通過@Deprecated(since="9")
註解,標記了finalize()
方法自JDK9開始被棄用。
不推薦使用的原因
-
finalize()方法不能保證執行。
還有另外一個方法能夠回收物件,Runtime.getRuntime().runFinalization(); 但是這隻能保證GC做出最大的努力,但是我們也不能finalize方法都能執行。我們還有一種方式能夠保證執行finalize()方法,Runtime.runFinalizersOnExit(true),這個方法已經被JDK棄用,因為這種方法本質上是不安全的,可能導致finalizers方法被活物件呼叫而其他執行緒正在並行操作這個物件,從而導致不正確的行為或者死鎖。 -
finalize()方法不像構造方法在鏈中工作,意味著像當你呼叫構造方法的時候,超類中的構造方法也會被隱含的呼叫,但是在finalize()方法的這種情況中,這種隱含的呼叫不會發生。超類中的finalize()方法需要顯示的呼叫。假設,你建立了一個類並且小心翼翼的寫了finalize()方法。一些人來extend了你的類,但是在子類中的finalize()塊中沒有呼叫super.finalize()方法。然後超類中finalize()方法將永遠都不會被呼叫。
-
任何有finalize()方法丟擲的異常都會被GC執行緒忽略而且不會被進一步傳播,事實上也不會在日誌檔案上記錄下來。
正確的姿勢
- 要在finalize()方法中一直呼叫super.finalize()。
- 考慮到不可預測預測性,不要在時間要求高的應用中使用finalize()。
- 不要使用Runtime.runFinalizersOnExit(true);方法,因為你可能將你的系統置於危險之中。
- 嘗試遵循下邊的模板使用finalize()方法。
@Override
protected void finalize() throws Throwable{
try{
//release resources here
}catch(Throwable t){
throw t;
}finally{
super.finalize();
}