Java基礎知識梳理&修飾符

private 修飾符

1.private修飾的變量和方法只在類內部可見。

2.在類內部,該類的所有的屬性和方法都是可以訪問的。

子類繼承父類的所有屬性和方法或子類擁有父類的所有屬性和方法是對的。但是父類的私有屬性和方法,對子類不可見,子類是無法直接訪問到的。即只是擁有,但是無法使用

public 修飾符

被聲明爲 public 的類、方法、構造方法和接口能夠被任何其他類訪問。如果幾個相互訪問的 public 類分佈在不同的包中,則需要導入相應 public 類所在的包。由於類的繼承性,類所有的公有方法和變量都能被其子類繼承。

protected 修飾符

1.子類與基類在同一包中:被聲明爲 protected 的變量、方法和構造器能被同一個包中的任何其他類訪問;

2.子類與基類不在同一包中:那麼在子類中,子類實例可以訪問其從基類繼承而來的 protected 方法,而不能訪問基類實例的protected方法。

protected 可以修飾數據成員,構造方法,方法成員,不能修飾類(內部類除外)

default 修飾符

default (即缺省,什麼也不寫): 在同一包內可見,不使用任何修飾符。使用對象:類、接口、變量、方法。

static 修飾符

1.靜態變量:

類變量也稱爲靜態變量,在類中以 static 關鍵字聲明,但必須在方法之外

無論一個類創建了多少個對象,類只擁有類變量的一份拷貝。

靜態變量儲存在靜態存儲區。經常被聲明爲常量,很少單獨使用static聲明變量。

靜態變量在第一次被訪問時創建,在程序結束時銷燬。

與實例變量具有相似的可見性。但爲了對類的使用者可見,大多數靜態變量聲明爲public類型。

默認值和實例變量相似。數值型變量默認值是0,布爾型默認值是false,引用類型默認值是null。變量的值可以在聲明的時候指定,也可以在構造方法中指定。此外,靜態變量還可以在靜態語句塊中初始化。

靜態變量可以通過:ClassName.VariableName的方式訪問。

2.靜態方法:static 關鍵字用來聲明獨立於對象的靜態方法。靜態方法不能使用類的非靜態變量。靜態方法從參數列表得到數據,然後計算這些數據。

3.靜態內部類:聲明爲static的內部類,成員內部類不能有static數據和static方法,但嵌套內部類可以。

final 修飾符

1.final靜態變量:

如果final修飾的是一個基本類型,就表示這個變量被賦予的值是不可變的。

如果final修飾的是一個對象,就表示這個變量被賦予的引用是不可變的。

靜態final變量可以在靜態初始化塊中初始化

2.final非靜態變量:

final修飾的非靜態變量在定義的時候初始化

非靜態final變量在初始化塊中初始化,不可在靜態初始化塊中初始化

非靜態final變量可以在類的構造器中初始化,但是靜態final變量不可以

非靜態final變量可以在類的構造器中初始化,但是靜態final變量不可以

3.final 方法:

類中的 final 方法可以被子類繼承,但是不能被子類修改。聲明 final 方法的主要目的是防止該方法的內容被修改。

4.final 類:

 final 類不能被繼承,沒有類能夠繼承 final 類的任何特性。

abstract 修飾符

1.抽象類:抽象類不能用來實例化對象,聲明抽象類的唯一目的是爲了將來對該類進行擴充。一個類不能同時被 abstract 和 final 修飾。如果一個類包含抽象方法,那麼該類一定要聲明爲抽象類,否則將出現編譯錯誤。

2.抽象方法:抽象方法是一種沒有任何實現的方法,該方法的的具體實現由子類提供。抽象方法不能被聲明成 final 和 static。任何繼承抽象類的子類必須實現父類的所有抽象方法,除非該子類也是抽象類。如果一個類包含若干個抽象方法,那麼該類必須聲明爲抽象類。抽象類可以不包含抽象方法。

synchronized 修飾符

1.同步實例方法

Java中的同步實例方法在擁有該方法的實例(對象)上同步。因此,每個實例的同步方法在不同的對象上同步:擁有它的實例。在一個同步實例方法中,只有一個線程可以執行。如果存在多個實例,則一次只能有一個線程可以在每個實例的同步實例方法內執行。每個實例一個線程。

2.同步靜態方法

同步靜態方法在同步靜態方法所屬的類的類對象上同步。由於每個類在Java VM中只存在一個類對象,因此在同一個類中的靜態同步方法中只能執行一個線程。

如果靜態同步方法位於不同的類中,則一個線程可以在每個類的靜態同步方法內執行。每個類一個線程,無論它調用哪個靜態同步方法。

3.實例方法中的同步塊

Java synchronized塊構造如何在括號中獲取對象——使用synchronized(this),由synchronized構造在括號中獲取的對象稱爲監視器對象。據說代碼在監視器對象上同步。同步實例方法使用它所屬的對象作爲監視對象。只有一個線程可以在同一監視器對象上同步的Java代碼塊內執行。

4.靜態方法中的同步塊

synchronized(Class.class)不同的對象上同步,那麼一個線程可以同時在每個方法內執行。

transient 修飾符

1. transient的作用及使用方法
我們都知道一個對象只要實現了Serilizable接口,這個對象就可以被序列化,java的這種序列化模式爲開發者提供了很多便利,我們可以不必關係具體序列化的過程,只要這個類實現了Serilizable接口,這個類的所有屬性和方法都會自動序列化。然而在實際開發過程中,我們常常會遇到這樣的問題,這個類的有些屬性需要序列化,而其他屬性不需要被序列化,打個比方,如果一個用戶有一些敏感信息(如密碼,銀行卡號等),爲了安全起見,不希望在網絡操作(主要涉及到序列化操作,本地序列化緩存也適用)中被傳輸,這些信息對應的變量就可以加上transient關鍵字。換句話說,這個字段的生命週期僅存於調用者的內存中而不會寫到磁盤裏持久化。

總之,java 的transient關鍵字爲我們提供了便利,你只需要實現Serilizable接口,將不需要序列化的屬性前添加關鍵字transient,序列化對象的時候,這個屬性就不會序列化到指定的目的地中。

2. transient 使用小結
一旦變量被transient修飾,變量將不再是對象持久化的一部分,該變量內容在序列化後無法獲得訪問。

transient關鍵字只能修飾變量,而不能修飾方法和類。注意,本地變量是不能被transient關鍵字修飾的。變量如果是用戶自定義類變量,則該類需要實現Serializable接口。

被transient關鍵字修飾的變量不再能被序列化,一個靜態變量不管是否被transient修飾,均不能被序列化。

3. transient使用細節——被transient關鍵字修飾的變量真的不能被序列化嗎?
我們知道在Java中,對象的序列化可以通過實現兩種接口來實現,若實現的是Serializable接口,則所有的序列化將會自動進行,若實現的是Externalizable接口,則沒有任何東西可以自動序列化,需要在writeExternal方法中進行手工指定所要序列化的變量,這與是否被transient修飾無關。 

volatile 修飾符

volatile 修飾的成員變量在每次被線程訪問時,都強制從共享內存中重新讀取該成員變量的值。而且,當成員變量發生變化時,會強制線程將變化值回寫到共享內存。這樣在任何時刻,兩個不同的線程總是看到某個成員變量的同一個值。一個 volatile 對象引用可能是 null。

1.保證可見性

將當前處理器 內部緩存 的數據寫回到 系統內存

這個寫回內存的操作會使在其他處理器裏 緩存了該內存地址的數據無效,當這些處理器對這個數據進行修改操作的時候,會重新從系統內存中把數據讀到處理器緩存裏。

2.禁止指令重排序

當程序執行到volatile 變量的讀操作或者寫操作時,在其前面的操作的更改肯定全部已經進行,且結果已經對後面的操作可見;在其後面的操作肯定還沒有進行;

在進行指令優化時,不能將在對volatile 變量訪問的語句放在其後面執行,也不能把volatile變量後面的語句放到其前面執行。

3.性能問題

volatile 相對於synchronized的優勢主要原因是兩點:簡易和性能。如果從讀寫兩方便來考慮:

volatile 讀操作開銷非常低,幾乎和非volatile 讀操作一樣

volatile 寫操作的開銷要比非volatile 寫操作多很多,因爲要保證可見性需要實現 內存界定,即便如此,volatile的總開銷仍然要比鎖獲取低。volatile 操作不會像鎖一樣 造成阻塞。

以上兩個條件表明,可以被寫入volatile 變量的這些有效值 獨立於任何程序的狀態,包括變量的當前狀態。大多數的編程情形都會與這兩個條件的其中之一衝突,使得volatile 不能像synchronized那樣普遍適用於實現線程安全。

因此,在能夠安全使用volatile 的情況下,volatile 可以提供一些優於鎖的可伸縮特性。如果讀操作的次數要遠遠超過寫操作,與鎖相比,volatile變量通常能夠減少同步的性能開銷。

4.應用場景

要使volatile 變量提供理想的線程安全,必須同時滿足以下兩個條件:

對變量的 寫操作不依賴於當前值。例如x++這樣的增量操作,它實際上是一個由讀取、修改、寫入操作序列組成的組合操作,必須以原子方式執行,而volatile 不能提供必須的原子特性。

該變量 沒有包含在其它變量的不變式中。

避免濫用volatile最重要的準則就是:只有在 狀態真正獨立於程序內其它內容時 才能使用volatile

5.狀態標誌

用volatile 來修飾一個Boolean狀態標誌,用於指示發生了某一次的重要事件,例如完成初始化或者請求停機

6.volatile bean 模式

volatile bean模式適用於將JavaBean作爲“榮譽結構”使用的框架。在volatile bean模式中,JavaBean被用作一組具有getter和/或setter方法的獨立屬性的容器。

volatile bean模式的基本原理是:很多框架爲易變數據的持有者提供了容器,但是放入這些容器中的對象必須是線程安全的。

在volatile bean模式中,JavaBean的所有數據成員都是volatile 類型的,並且 getter和setter方法必須非常普通,除了獲取或設置相應的屬性外,不能包含任何邏輯。此外,對於對象引用的數據成員,引用的對象必須是有效不可變的。

7.開銷較低的讀/寫鎖策略

如果讀操作遠遠超過寫操作,您可以結合使用內部鎖和volatile變量來減少公共代碼路徑的開銷。下面的代碼中使用synchronized確保增量操作是原子的,並使用volatile保證當前結果的可見性。如果更新不頻繁的話,該方法可實現更好的性能,因爲讀路徑的開銷僅僅涉及volatile讀操作,這通常要優於一個無競爭的鎖獲取的開銷。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章