1. 屬性:getters 和 setters
當數十名程序員同時開發一個大型項目時,如果他們對存儲在類字段中的數據的處理方式不同,問題往往會突然出現。
也許人們沒有詳細研究類文檔,或者它沒有描述每個案例。因此,經常會出現對象的內部數據“損壞”,從而使對象無效的情況。
為了避免這些情況,習慣上在 Java 中將所有類字段設為私有。只有類的方法可以修改類的變量。其他類的任何方法都不能直接訪問變量。
如果您希望其他類能夠獲取或更改您類對像中的數據,您需要向您的類添加兩個方法——get 方法和 set 方法。例子:
代碼 | 筆記 |
---|---|
|
private name field通過構造函數初始化字段 getName() — 此方法返回 name 字段的值setName() — 此方法更改 name 字段的值 |
沒有其他類可以直接更改名稱字段的值。如果有人需要獲取 name 字段的值,他們將不得不調用對像getName()
上的方法Person
。如果某些代碼想要更改名稱字段的值,則需要調用對像setName()
上的方法Person
。
該getName()
方法也稱為“名稱字段的獲取器setName()
”,該方法稱為“名稱字段的設置器”。
這是一種非常常見的方法。在 80-90% 的所有 Java 代碼中,您永遠不會在類中看到公共變量。相反,它們將被聲明private
(或protected
),並且每個變量都有公共的 getter 和 setter。
這種方法使代碼更長,但更可靠。
直接訪問一個類變量就像讓你的車通過雙黃線轉彎:它更容易也更快,但如果每個人都這樣做,那麼每個人的情況都會變得更糟。
假設您要創建一個描述點 ( x
, y
) 的類。以下是新手程序員的做法:
class Point
{
public int x;
public int y;
}
有經驗的 Java 程序員會這樣做:
代碼 |
---|
|
代碼更長嗎?無疑。
但是您可以為 getter 和 setter 添加參數驗證。例如,您可以確保 和x
始終y
大於零(或不小於零)。例子:
代碼 | 筆記 |
---|---|
|
2. 對像生命週期
您已經知道對像是使用運算符創建的new
,但是如何刪除對象呢?它們不會永遠存在。內存不足。
在許多編程語言中,例如 C++,都有一個專門delete
用於刪除對象的運算符。但是這在 Java 中是如何工作的呢?
在 Java 中,一切的安排都略有不同。Java 沒有刪除運算符。這是否意味著在 Java 中對像不會被刪除?不,它們當然被刪除了。否則,Java 應用程序會很快耗盡內存,而且不會有幾個月不間斷運行的程序。
在 Java 中,對象的刪除是完全自動化的。Java 機器本身處理對象的刪除。這個過程稱為垃圾收集,收集垃圾的機制稱為垃圾收集器( GC )。
那麼 Java 機器如何知道何時刪除一個對象呢?
垃圾收集器將所有對象分為“可達”和“不可達”。如果至少有一個對象的引用,則認為它是可達的。如果沒有引用某個對象的變量,則該對像被認為是不可訪問的,並被聲明為垃圾,這意味著它可以被刪除。
在 Java 中,您不能創建對現有對象的引用——您只能分配您已有的引用。如果我們刪除對一個對象的所有引用,那麼它就永遠丟失了。
循環引用
在我們遇到一個簡單的反例之前,這個邏輯聽起來很棒:假設我們有兩個相互引用的對象(存儲對彼此的引用)。沒有其他對象存儲對這些對象的引用。
這些對像不能從代碼中訪問,但它們仍然被引用。
這就是垃圾收集器將對象分為可達和不可達,而不是“已引用”和“未引用”的原因。
可達對象
首先,將 100% 存活的對象添加到可達列表中。例如,當前線程 ( Thread.current()
) 或控制台 InputStream ( System.in
)。
然後,可達對象列表會擴展,以包括由初始可達對象集引用的對象。然後再次擴展以包含此擴展集引用的對象,依此類推。
這意味著如果有一些對像只相互引用,但是沒有辦法從可達對像中到達它們,那麼這些對象將被認為是垃圾,將被刪除。
3.垃圾收集
內存碎片
與對象刪除相關的另一個重點是內存碎片。如果你不斷地創建和刪除對象,很快內存就會嚴重碎片化:佔用的內存區域將散佈在未佔用的內存區域中。
結果,我們很容易陷入無法創建大對象(例如,具有一百萬個元素的數組)的情況,因為沒有大塊的空閒內存。換句話說,可能有空閒內存,甚至很多,但可能沒有大的連續空閒內存塊
內存優化(碎片整理)
Java 機器以特定的方式解決了這個問題。它看起來像這樣:
內存分為兩部分。所有對象的創建(和刪除)僅佔內存的一半。當需要清理內存中的漏洞時,前半部分的所有對像都被複製到後半部分。但是它們是緊挨著複製的,所以沒有孔。
該過程大致如下所示:
第一步:創建對像後
第二步:“洞”的出現
第三步:消除“洞”
這就是您不需要刪除對象的原因。Java 機器只是將所有可到達的對象複製到一個新位置,並釋放用於存儲對象的整個內存區域。
GO TO FULL VERSION