成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Java中的final、finally和finalize有什么不同

這篇文章主要講解了“Java中的final、finally和finalize有什么不同”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Java中的final、finally和finalize有什么不同”吧!

成都創(chuàng)新互聯(lián)專注于萊山企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,商城建設(shè)。萊山網(wǎng)站建設(shè)公司,為萊山等地區(qū)提供建站服務(wù)。全流程按需網(wǎng)站制作,專業(yè)設(shè)計,全程項目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

首先可以從語法和使用角度出發(fā)簡單介紹三者的不同:

final 可以用來修飾類、方法、變量,分別有不同的意義,final 修飾的 class 代表不可以繼承擴(kuò)展,final 的變量是不可以修改的,而 final 的方法也是不可以重寫的(override)。

finally 是 Java 保證重點代碼一定要被執(zhí)行的一種機(jī)制。可以使用 try-finally 或者 try-catch-finally 來進(jìn)行類似關(guān)閉 JDBC 連接、保證 unlock 鎖等動作。

finalize 是基礎(chǔ)類 java.lang.Object 的一個方法,設(shè)計目的是保證對象在被垃圾收集前完成特定資源的回收。finalize 機(jī)制現(xiàn)在已經(jīng)不推薦使用,并且在 JDK 9 開始被標(biāo)記為 deprecated。

如果只回答到這里,就會沒有亮點,我們可以再深入地去介紹三者的不同,比如從性能、并發(fā)、對象生命周期或垃圾收集基本過程等方面去談?wù)勛约旱睦斫狻?/p>

final

使用 final 關(guān)鍵字可以明確表示代碼的語義、邏輯意圖,比如:

可以將方法或者類聲明為 final,這樣就可以明確告知別人,這些行為是不許修改的。Java 核心類庫的定義或源碼,比如 java.lang 包下面的很多類,相當(dāng)一部分都被聲明成為 final class,比如我們常見的 String 類,在第三方類庫的一些基礎(chǔ)類中同樣如此,這可以有效避免 API 使用者更改基礎(chǔ)功能,某種程度上,這是保證平臺安全的必要手段。

使用 final 修飾參數(shù)或者變量,也可以清楚地避免意外賦值導(dǎo)致的編程錯誤,甚至,有人明確推薦將所有方法參數(shù)、本地變量、成員變量聲明成 final。

final 變量產(chǎn)生了某種程度的不可變(immutable)的效果,所以,可以用于保護(hù)只讀數(shù)據(jù),尤其是在并發(fā)編程中,因為明確地不能再賦值 final 變量,有利于減少額外的同步開銷,也可以省去一些防御性拷貝的必要。

關(guān)于 final 也許會有性能的好處,很多文章或者書籍中都介紹了可在特定場景提高性能,比如,利用 final 可能有助于 JVM 將方法進(jìn)行內(nèi)聯(lián),可以改善編譯器進(jìn)行條件編譯的能力等等。我在之前一篇文章進(jìn)行了介紹,想了解的可以點擊查閱。

final 與 immutable

在前面介紹了 final 在實踐中的益處,需要注意的是,final 并不等同于 immutable,比如下面這段代碼:

final List strList = new ArrayList<>();

strList.add("wupx");

strList.add("huxy");

List loveList = List.of("wupx", "huxy");

loveList.add("love");

final 只能約束 strList 這個引用不可以被賦值,但是 strList 對象行為不被 final 影響,添加元素等操作是完全正常的。如果我們真的希望對象本身是不可變的,那么需要相應(yīng)的類支持不可變的行為。在上面這個例子中,List.of 方法創(chuàng)建的本身就是不可變 List,最后那句 add 是會在運行時拋出異常的。

Immutable 在很多場景是非常棒的選擇,某種意義上說,Java 語言目前并沒有原生的不可變支持,如果要實現(xiàn) immutable 的類,我們需要做到:

將 class 自身聲明為 final,這樣別人就不能擴(kuò)展來繞過限制了。

將所有成員變量定義為 private 和 final,并且不要實現(xiàn) setter 方法。

通常構(gòu)造對象時,成員變量使用深度拷貝來初始化,而不是直接賦值,這是一種防御措施,因為你無法確定輸入對象不被其他人修改。

如果確實需要實現(xiàn) getter 方法,或者其他可能會返回內(nèi)部狀態(tài)的方法,使用 copy-on-write 原則,創(chuàng)建私有的 copy。

關(guān)于 setter/getter 方法,很多人喜歡直接用 IDE 或者 Lombok 一次全部生成,建議最好確定有需要時再實現(xiàn)。

finally

對于 finally,知道怎么使用就足夠了。需要關(guān)閉的連接等資源,更推薦使用 Java 7 中添加的 try-with-resources 語句,因為通常 Java 平臺能夠更好地處理異常情況,還可以減少代碼量。

另外,有一些常被考到的 finally 問題。比如,下面代碼會輸出什么?

try {

// do something

System.exit(1);

} finally{

System.out.println("Hello,I am finally。");

}

上面 finally 里面的代碼是不會被執(zhí)行的,因為 try-catch 異常退出了。

像其他 finally 中的代碼不會執(zhí)行的情況還有:

// 死循環(huán)

try{

while(ture){

System.out.println("always run");

}

}finally{

System.out.println("ummm");

}

// 線程被殺死

當(dāng)執(zhí)行 try-finally 的線程被殺死時,finally 中的代碼也無法執(zhí)行。

finalize

對于 finalize,是不推薦使用的,在 Java 9 中,已經(jīng)將 Object.finalize() 標(biāo)記為 deprecated。

為什么呢?因為無法保證 finalize 什么時候執(zhí)行,執(zhí)行的是否符合預(yù)期。使用不當(dāng)會影響性能,導(dǎo)致程序死鎖、掛起等。

通常來說,利用上面的提到的 try-with-resources 或者 try-finally 機(jī)制,是非常好的回收資源的辦法。如果確實需要額外處理,可以考慮 Java 提供的 Cleaner 機(jī)制或者其他替代方法。

為什么不推薦使用 finalize?

前面簡單介紹了 finalize 是不推薦使用的,究竟為什么不推薦使用呢?

finalize 的執(zhí)行是和垃圾收集關(guān)聯(lián)在一起的,一旦實現(xiàn)了非空的 finalize 方法,就會導(dǎo)致相應(yīng)對象回收呈現(xiàn)數(shù)量級上的變慢。

finalize 被設(shè)計成在對象被垃圾收集前調(diào)用,JVM 要對它進(jìn)行額外處理。finalize 本質(zhì)上成為了快速回收的阻礙者,可能導(dǎo)致對象經(jīng)過多個垃圾收集周期才能被回收。

finalize 拖慢垃圾收集,導(dǎo)致大量對象堆積,也是一種典型的導(dǎo)致 OOM 的原因。

要確?;厥召Y源就是因為資源都是有限的,垃圾收集時間的不可預(yù)測,可能會極大加劇資源占用。

finalize 會掩蓋資源回收時的出錯信息。

因此對于消耗非常高頻的資源,千萬不要指望 finalize 去承擔(dān)資源釋放的主要職責(zé)。建議資源用完即顯式釋放,或者利用資源池來盡量重用。

下面給出 finalize 掩蓋資源回收時的出錯信息的例子,讓我們來看 java.lang.ref.Finalizer 的源代碼:

private void runFinalizer(JavaLangAccess jla) {

// ... 省略部分代碼

try {

Object finalizee = this.get();

if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {

jla.invokeFinalize(finalizee);

// Clear stack slot containing this variable, to decrease

// the chances of false retention with a conservative GC

finalizee = null;

}

} catch (Throwable x) { }

super.clear();

}

看過之前講解異常文章的朋友,應(yīng)該可以很快看出 Throwable 是被吞掉的,也就意味著一旦出現(xiàn)異?;蛘叱鲥e,得不到任何有效信息。

有更好的方法替代 finalize 嗎?

Java 平臺目前在逐步使用 java.lang.ref.Cleaner 來替換掉原有的 finalize 實現(xiàn)。Cleaner 的實現(xiàn)利用了幻象引用(PhantomReference),這是一種常見的所謂 post-mortem 清理機(jī)制。利用幻象引用和引用隊列,可以保證對象被徹底銷毀前做一些類似資源回收的工作,比如關(guān)閉文件描述符(操作系統(tǒng)有限的資源),它比 finalize 更加輕量、更加可靠。

每個 Cleaner 的操作都是獨立的,有自己的運行線程,所以可以避免意外死鎖等問題。

我們可以為自己的模塊構(gòu)建一個 Cleaner,然后實現(xiàn)相應(yīng)的清理邏輯,具體代碼如下:

/**

* Cleaner 是一個用于關(guān)閉資源的類,功能類似 finalize 方法

* Cleaner 有自己的線程,在所有清理操作完成后,自己會被 GC

* 清理中拋出的異常會被忽略

*

* 清理方法(一個 Runnable)只會運行一次。會在兩種情況下運行:

* 1. 注冊的 Object 處于幻象引用狀態(tài)

* 2. 顯式調(diào)用 clean 方法

*

* 通過幻象引用和引用隊列實現(xiàn)

* 可以注冊多個對象,通常被定義為靜態(tài)(減少線程數(shù)量)

* 注冊對象后返回的Cleanable對象用于顯式調(diào)用 clean 方法

* 實現(xiàn)清理行為的對象(下面的 state),不能擁有被清理對象的引用

* 如果將下面的 State 類改為非靜態(tài),第二個 CleaningExample 將不會被 clean,

* 因為非靜態(tài)內(nèi)部類持有外部對象的引用,外部對象無法進(jìn)入幻象引用狀態(tài)

*/

public class CleaningExample implements AutoCloseable {

public static void main(String[] args) {

try {

// 使用JDK7的try with Resources顯式調(diào)用clean方法

try (CleaningExample ignored = new CleaningExample()) {

throw new RuntimeException();

}

} catch (RuntimeException ignored) {

}

// 通過GC調(diào)用clean方法

new CleaningExample();

System.gc();

}

private static final Cleaner CLEANER = Cleaner.create();

// 如果是非靜態(tài)內(nèi)部類,則會出錯

static class State implements Runnable {

State() {

}

@Override

public void run() {

System.out.println("Cleaning called");

}

}

private final State state;

private final Cleaner.Cleanable cleanable;

public CleaningExample() {

this.state = new State();

this.cleanable = CLEANER.register(this, state);

}

@Override

public void close() {

cleanable.clean();

}

}

其中,將 State 定義為 static,就是為了避免普通的內(nèi)部類隱含著對外部對象的強引用,因為那樣會使外部對象無法進(jìn)入幻象可達(dá)的狀態(tài)。

從可預(yù)測性的角度來判斷,Cleaner 或者幻象引用改善的程度仍然是有限的,如果由于種種原因?qū)е禄孟笠枚逊e,同樣會出現(xiàn)問題。所以,Cleaner 適合作為一種最后的保證手段,而不是完全依賴 Cleaner 進(jìn)行資源回收。

感謝各位的閱讀,以上就是“Java中的final、finally和finalize有什么不同”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Java中的final、finally和finalize有什么不同這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

文章標(biāo)題:Java中的final、finally和finalize有什么不同
當(dāng)前網(wǎng)址:http://jinyejixie.com/article30/psphpo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃營銷型網(wǎng)站建設(shè)、網(wǎng)站改版、網(wǎng)站營銷、網(wǎng)站設(shè)計公司、虛擬主機(jī)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)