Java提高学习之Object(3)
終止
問:?finalize()方法是用來做什么的?
答:?finalize()方法可以被子類對(duì)象所覆蓋,然后作為一個(gè)終結(jié)者,當(dāng)GC被調(diào)用的時(shí)候完成最后的清理工作(例如釋放系統(tǒng)資源之類)。這就是終止。默認(rèn)的finalize()方法什么也不做,當(dāng)被調(diào)用時(shí)直接返回。
對(duì)于任何一個(gè)對(duì)象,它的finalize()方法都不會(huì)被JVM執(zhí)行兩次。如果你想讓一個(gè)對(duì)象能夠被再次調(diào)用的話(例如,分配它的引用給一個(gè)靜態(tài)變量),注意當(dāng)這個(gè)對(duì)象已經(jīng)被GC回收的時(shí)候,finalize()方法不會(huì)被調(diào)用第二次。
問:?有人說要避免使用finalize()方法,這是真的嗎?
答:?通常來講,你應(yīng)該盡量避免使用finalize()。相對(duì)于其他JVM實(shí)現(xiàn),終結(jié)器被調(diào)用的情況較少——可能是因?yàn)榻K結(jié)器線程的優(yōu)先級(jí)別較低的原因。如果你依靠終結(jié)器來關(guān)閉文件或者其他系統(tǒng)資源,可能會(huì)將資源耗盡,當(dāng)程序試圖打開一個(gè)新的文件或者新的系統(tǒng)資源的時(shí)候可能會(huì)崩潰,就因?yàn)檫@個(gè)緩慢的終結(jié)器。
問:?應(yīng)該使用什么來替代終結(jié)器?
答:?提供一個(gè)明確的用來銷毀這個(gè)對(duì)象的方法(例如,java.io.FileInputStream的void close()方法),并且在代碼中使用try - finally結(jié)構(gòu)來調(diào)用這個(gè)方法,以確保無論有沒有異常從try中拋出,都會(huì)銷毀這個(gè)對(duì)象。參考下面釋放鎖的代碼:
1 Lock l = ...; // ... is a placeholder for the actual lock-acquisition code 2 l.lock(); 3 try 4 { 5 // access the resource protected by this lock 6 } 7 finally 8 { 9 l.unlock(); 10 }這段代碼保證了無論try是正常結(jié)束還是拋出異常都會(huì)釋放鎖。
問:?什么情況下適合使用終結(jié)器?
答:?終結(jié)器可以作為一個(gè)安全保障,以防止聲明的終結(jié)方法(像是java.io.FileOutputStream對(duì)象的close()方法或者java.util.concurrent.Lock對(duì)象的Lock()方法)沒有被調(diào)用。萬一這種情況出現(xiàn),終結(jié)器可以在最后被調(diào)用,釋放臨街資源。
問:?怎么寫finalize()?
答:?可以遵循下面這個(gè)模式寫finalize()方法:
1 @Override 2 protected void finalize() throws Throwable 3 { 4 try 5 { 6 // Finalize the subclass state. 7 // ... 8 } 9 finally 10 { 11 super.finalize(); 12 } 13 }? ? 子類終結(jié)器一般會(huì)通過調(diào)用父類的終結(jié)器來實(shí)現(xiàn)。當(dāng)被調(diào)用時(shí),先執(zhí)行try模塊,然后再在對(duì)應(yīng)的finally中調(diào)用super.finalize();這就保證了無論try會(huì)不會(huì)拋出異常父類都會(huì)被銷毀。
問:?如果finalize()拋出異常會(huì)怎樣?
答:?當(dāng)finalize()拋出異常的時(shí)候會(huì)被忽略。而且,對(duì)象的終結(jié)將在此停止,導(dǎo)致對(duì)象處在一種不確定的狀態(tài)。如果另一個(gè)進(jìn)程試圖使用這個(gè)對(duì)象的話,將產(chǎn)生不確定的結(jié)果。通常拋出異常將會(huì)導(dǎo)致線程終止并產(chǎn)生一個(gè)提示信息,但是從finalize()中拋出異常就不會(huì)。
問:?我想實(shí)踐一下finalize()方法,能提供一個(gè)范例嗎?
答:?參考代碼清單1.
1 class LargeObject 2 { 3 byte[] memory = new byte[1024*1024*4]; 4 5 @Override 6 protected void finalize() throws Exception 7 { 8 System.out.println("finalized"); 9 } 10 } 11 12 public class FinalizeDemo 13 { 14 public static void main(String[] args) 15 { 16 while (true) 17 new LargeObject(); 18 } 19 }代碼清單1:實(shí)踐finalize()
? ? 代碼清單1中的代碼寫了一個(gè)FinalizeDemo程序,重復(fù)地對(duì)largeObject類實(shí)例化。每一個(gè)Largeobject對(duì)象將產(chǎn)生4M的數(shù)組。在這種情況下,由于沒有指向該對(duì)象的引用,所以LargeObject對(duì)象將被GC回收。
GC會(huì)調(diào)用對(duì)象的finalize()方法來回收對(duì)象。LargeObject重載的finalize()方法被調(diào)用的時(shí)候會(huì)想標(biāo)準(zhǔn)輸出流打印一條信息。它沒有調(diào)用父類的finalize()方法,因?yàn)樗母割愂荗bject,即父類的finalize()方法什么也不做。
編譯(javac FinalizeDemo.java)并運(yùn)行(java FinalizeDemo)代碼清單1.當(dāng)我在我的環(huán)境下(64位win7平臺(tái))使用JDK7u6來編譯運(yùn)行的時(shí)候,我看到一列finalized的信息。但是在JDK8的環(huán)境下時(shí),在幾行finalized之后拋出了java.lang.OutOfMemoryError。
因?yàn)閒inalize()方法對(duì)于虛擬機(jī)來說不是輕量級(jí)的程序,所以不能保證你一定會(huì)在你的環(huán)境下觀察到輸出信息。
得到對(duì)象的類
問:?gerClass()方法是用來做什么的?
答:?通過gerClass()方法可以得到一個(gè)和這個(gè)類有關(guān)的java.lang.Class對(duì)象。返回的Class對(duì)象是一個(gè)被static synchronized方法封裝的代表這個(gè)類的對(duì)象;例如,static sychronized void foo(){}。這也是指向反射API。因?yàn)檎{(diào)用gerClass()的對(duì)象的類是在內(nèi)存中的,保證了類型安全。
問:?還有其他方法得到Class對(duì)象嗎?
答:?獲取Class對(duì)象的方法有兩種??梢允褂妙愖置娉A?#xff0c;它的名字和類型相同,后綴位.class;例如,Account.class。另外一種就是調(diào)用Class的foeName()方法。類字面常量更加簡潔,并且編譯器強(qiáng)制類型安全;如果找不到指定的類編譯就不會(huì)通過。通過forname()可以動(dòng)態(tài)地通過指定包名載入任意類型地引用。但是,不能保證類型安全,可能會(huì)導(dǎo)致Runtime異常。
轉(zhuǎn)載于:https://www.cnblogs.com/sunfie/p/5134254.html
總結(jié)
以上是生活随笔為你收集整理的Java提高学习之Object(3)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [翻译]opengl扩展教程2
- 下一篇: Java Web开发Tomcat中三种部