Java中的“ final”關(guān)鍵字如何工作?(我仍然可以修改對象)
你總是允許初始化一個final變量。編譯器確保你只能執(zhí)行一次。
請注意,對存儲在final變量中的對象的調(diào)用方法與的語義無關(guān)final。換句話說:final僅與引用本身有關(guān),而與引用對象的內(nèi)容無關(guān)。
Java沒有對象不變性的概念。這是通過精心設(shè)計對象來實現(xiàn)的,這是一項艱巨的工作。
這是一個最喜歡的面試問題。帶著這些問題,訪問者試圖找出你對對象的構(gòu)造,方法,類變量(靜態(tài)變量)和實例變量的理解程度。
import java.util.ArrayList;import java.util.List;class Test { private final List foo; public test() {foo = new ArrayList();foo.add('foo'); // Modification-1 } public void setFoo(List foo) { //this.foo = foo; Results in compile time error. }}
在上述情況下,我們?yōu)椤?Test”定義了一個構(gòu)造函數(shù),并為其指定了“ setFoo”方法。
關(guān)于構(gòu)造器: 構(gòu)造函數(shù)可以調(diào)用只有一個使用每個對象的創(chuàng)建時間new關(guān)鍵字。你不能多次調(diào)用構(gòu)造函數(shù),因為構(gòu)造函數(shù)的目的不是這樣做的。
關(guān)于方法:可以根據(jù)需要多次調(diào)用方法(甚至永遠不會調(diào)用),并且編譯器知道該方法。
場景1
private final List foo; // 1
foo是實例變量。當我們創(chuàng)建Test類對象時,實例變量foo將被復制到Test類對象中。如果我們foo在構(gòu)造函數(shù)內(nèi)部分配,則編譯器知道構(gòu)造函數(shù)將僅被調(diào)用一次,因此在構(gòu)造函數(shù)內(nèi)部分配它沒有問題。
如果我們foo在一個方法內(nèi)部賦值,編譯器就會知道一個方法可以被多次調(diào)用,這意味著必須多次更改該值,而final變量是不允許的。因此編譯器認為構(gòu)造函數(shù)是一個不錯的選擇!你只能一次將值分配給最終變量。
方案2
private static final List foo = new ArrayList();
foo現(xiàn)在是一個靜態(tài)變量。當我們創(chuàng)建Test類的實例時,foo不會被復制到對象,因為它foo是靜態(tài)的。現(xiàn)在foo不是每個對象的獨立屬性。這是Test類的屬性。但是foo可以被多個對象看到,如果每個使用new關(guān)鍵字創(chuàng)建的對象最終將調(diào)用Test構(gòu)造函數(shù),則該構(gòu)造函數(shù)會在創(chuàng)建多個對象時更改值(記住static foo并不是在每個對象中都復制,而是在多個對象之間共享)
場景3
t.foo.add('bar'); // Modification-2
以上Modification-2是你的問題。在上述情況下,你沒有更改第一個引用的對象,而是在foo其中添加了允許的內(nèi)容。如果你嘗試將a分配new ArrayList()給foo引用變量,則編譯器會抱怨。規(guī)則如果已初始化final變量,則無法將其更改為引用其他對象。(在這種情況下ArrayList)
final類不能被子類化final方法不能被覆蓋。(此方法在超類中)最終方法可以重寫。(以語法方式閱讀。此方法在子類中)
解決方法在Java中,我們使用final帶有變量的關(guān)鍵字來指定其值不被更改。但是我看到你可以在類的構(gòu)造函數(shù)/方法中更改值。同樣,如果變量是static,則為編譯錯誤。
這是代碼:
import java.util.ArrayList;import java.util.List;class Test { private final List foo; public Test() { foo = new ArrayList(); foo.add("foo"); // Modification-1 } public static void main(String[] args) { Test t = new Test(); t.foo.add("bar"); // Modification-2 System.out.println("print - " + t.foo); }}
上面的代碼工作正常,沒有錯誤。
現(xiàn)在將變量更改為static:
private static final List foo;
現(xiàn)在是編譯錯誤。這final真的如何運作?
相關(guān)文章:
1. javascript - 關(guān)于<a>元素與<input>元素的JS事件運行問題2. css3 - 純css實現(xiàn)點擊特效3. MySQL中的enum類型有什么優(yōu)點?4. android下css3動畫非常卡,GPU也不差啊5. java - 為什么第一個線程已經(jīng)釋放了鎖,第二個線程卻不行?6. mysql - 記得以前在哪里看過一個估算時間的網(wǎng)站7. javascript - vscode alt+shift+f 格式化js代碼,通不過eslint的代碼風格檢查怎么辦。。。8. 大家好,我想請問一下怎么做搜索欄能夠搜索到自己網(wǎng)站的內(nèi)容。9. python - 啟動Eric6時報錯:’qscintilla_zh_CN’ could not be loaded10. mysql - 查詢字段做了索引為什么不起效,還有查詢一個月的時候數(shù)據(jù)都是全部出來的,如果分拆3次的話就沒問題,為什么呢。
