【1】Java中常見通路修飾符
權限範圍:
private < default < protected < public
。了解記憶則為:
自身->同一包->包和子類->所有
修飾符 | 被修飾者 | 描述 |
public | 外部類,接口,構造器,内部類,方法,成員屬性 | 任意可通路 |
protectd | 内部類,構造器,方法,成員屬性 | 包内通路或包外子類 |
default | 外部類,内部類,接口,構造器,方法,成員屬性 | 同一包内通路 |
private | 内部類,構造器,方法,成員屬性 | 隻能夠在它們被聲明的内部通路 |
public
公共的
類、成員變量和方法
都可以毫無限制的被其它Java程式所使用。
protected
相比default有更高的通路權限。隻有
成員變量和方法
能夠被聲明為protected。父類的protected屬性能被它的所有子類所共享。即使子類和父類不在同一包中,這種通路也是支援的。
内部類可以被protected修飾。
default/friendly
類中的資料、方法和它本身能夠被聲明為預設default。類中所有default成員都可以被本包中的其它類所通路。
你可以了解為這是一種 包權限
private
私有
成員變量和方法
(非外部類)隻能被聲明它們的類的執行個體所使用。
内部類可以被private修飾。
方法重載的隐私:
重載後的方法修飾符不能低于被重載的方法,比如父類是protected,子類中重載方法不能置為private。
除了上述基本的通路符之外,下表描述了Java中的其它描述符。它們能夠改變類和它的成員(如:方法、變量和内部類)的行為。
【2】Java幾個常見的非通路修飾符
修飾符 | 類/内部類 | 方法 | 變量 |
static | 一個靜态内部類是其父類的成員,但不是其父類執行個體對象的成員 | 一個靜态方法可以直接被類通路,并且被該類的對象共享 | 靜态變量是類級變量且在JVM中隻能夠出現一次 |
abstract | 抽象類不能夠被執行個體化,它隻能被其他類所繼承 | 抽象方法隻能被聲明在抽象類中,它的實作代碼隻能被包含在子類中 | 不适用 |
synchronized | 不适用 | 它在類上加了一個螢幕,使得通路該方法隻能通過獲得該方法所屬對象的鎖來進行 | |
transient | 變量不能夠被序列化 | ||
final | 類不能被繼承 | 方法不能被重寫 | 變量不能夠被序列化,變量值為常量不可更改 |
final
final修飾符隻能夠作用在類、方法和變量上。它的作用是所有被final修飾的内容不能被改變。
用于修飾類、屬性和方法;
- 被final修飾的類不可以被繼承
- 被final修飾的方法不可以被重寫
- 被final修飾的變量不可以被改變,被final修飾不可變的是變量的引用,而不是引用指向的内容,引用指向的内容是可以改變的
static
static修飾符可以被應用在變量、方法、代碼段和内部類中。如果需要Java執行個體變量被存儲在單獨的記憶體中,或需要變量對一個單獨類的所有對象所通用,那麼靜态修飾符需要被應用在該變量的聲明中。
- 靜态方法:Java的靜态方法對類是通用的并且并不和Java執行個體相關聯。盡管靜态方法能夠自由的通路類的靜态資料和方法,但是它們并不能使用類的非靜态功能。靜态方法不能夠被重載為非靜态的。對于Java靜态方法不能夠使用this關鍵字。
- 靜态塊:靜态代碼塊在類加載時隻執行一次。先與構造函數執行。
- 靜态變量:Java的執行個體變量使用單獨的空間進行存儲。如果需要變量對一個類的所有對象都是通用的,那麼這個變量就需要被聲明為靜态的。類的所有執行個體對象都可以修改該類的靜态變量。此外,使用對象執行個體修改靜态成員并不是唯一手段,也可以直接使用java類來修改。靜态變量也可以被Java對象的方法所通路。當一個常量的值在編譯器就已經知曉了,它就需要使用static關鍵字來聲明為final類型。
- 靜态内部類:隻有内部類能夠使用static修飾符來聲明,在Java中它被稱為靜态嵌套類。
native
native修飾符隻能夠修飾方法。native修飾符意味着方法的實作體是在JVM之外。通常是用C/C++編寫的本地代碼塊。
注意:抽象方法的實作體是在子類中,而native方法的實作體則完全不在Java的虛拟記憶體中,而是在其它程式庫中。如 *.dll檔案。
transient
transient修飾符隻能夠應用在變量中,transient變量不做為它所屬對象的持久狀态的一部分進行存儲。它并不需要被序列化,主要用作安全鍵(security key)或者連接配接(connection)等。
synchronized
synchronized修飾符在多線程程式中對臨界區代碼的通路進行控制。
synchronized關鍵字是保持代碼線程安全的工具之一。
對于某一對象的一個同步方法進行交叉通路是不可能的。當一個線程在執行某一對象的同步方法時,所有調用該同步方法的其它線程都将被阻塞直到第一個線程完成對該方法的調用。
其次,當一個同步方法執行結束時,對相同對象的後續同步方法調用,它會自動建立之前發生(happens-before)的順序關系。這保證了該對象的狀态更改對所有的線程都可見。
當你将一段代碼塊标記為同步化時,你需要使用對象作為該同步塊的參數。當一個執行線程到達該代碼塊時,它首先需要等待在該對象的同步塊上已經沒有其它的執行線程。然而,一個線程可以進入不同對象鎖定的同步方法塊。
但對同一對象的非同步方法可以直接方法而無需鎖檢測。
如果你同步化的是靜态方法,那麼你同步時擷取的是該方法類的鎖而不是執行個體的。這就意味着當你同步的是靜态方法時,整個類都将被阻塞。這樣其它的靜态同步方法也将被阻塞。
當一個線程進入同步化執行個體的方法時,其它線程則不能夠再進入該執行個體的其它同步化方法。
當一個線程進入同步化的靜态方法時,其它線程則不能夠再進入該類的其它同步化靜态方法。
注意:同步化的靜态方法和同步化的非靜态方法之間是沒有多少聯系的。例如:如果靜态和非靜态同步方法能夠并發的執行,就需要将你的非靜态方法顯式的聲明為在它自己的類上進行同步(如:同步MyClass.class{…})。
volatile
隻有變量能夠被定義為volatile。這些變量可能會被異步修改,是以編譯器需要對他們額外的關注。volatile修飾符保證任何讀取該字段的線程都能夠擷取它的最近修改值。
volatile和synchronize之間的差別:
volatile關鍵字隻用來線上程記憶體和主記憶體之間同步單個變量值,synchronized關鍵字用來同步線程記憶體和主記憶體之間的所有變量值以及如何鎖定和釋放一個螢幕。synchronized比volatile有着更大的開銷。
volatile變量不允許出現和目前主存中的資料值不同的的本地副本。
更準确地說,被聲明為volatile的變量必須保證它的資料值在所有線程的中是同步的。也就是當你在任一線程中通路或者更新一個變量時,所有其它線程能夠立即通路到相同的值。
參考博文:從記憶體可見性看Volatile、原子變量和CAS算法
abstract
abstract修飾符适用于類和方法。抽象類不能夠被執行個體化,它必須被繼承才能夠通路。abstract不能夠應用到類的成員變量。
注意:
- 如果類包含一個或多個抽象方法,編譯器将強制該類必須聲明為抽象的。
- abstract類和final類是相對的。final類不能夠被繼承,而抽象類必須被繼承。
- 抽象類不一定擁有抽象方法,但是通常會有抽象方法。
設計上,你希望基類對繼承類僅僅隻作為接口。這意味着你不希望任何人執行個體化該基類。你隻想進行向上類型轉換(隐式轉換,它能夠提供多态性),這樣就隻能使用該基類的接口了。這是通過使用abstract關鍵字來修飾該類實作的。
提供限制來不執行個體化抽象類,這樣就需要任何使用該抽象類的人來實作它,并提供多态性。