Java提供了許多非存取修飾符來實現許多其他功能。
static
修飾符用於建立類方法和變數。final
修飾符用於完成類,方法和變數的實現。abstract
修飾符用於建立抽象類和方法。synchronized
和volatile
修飾符,用於執行緒。下面來逐個了解和學習這些非存取修飾符。
1.1. 靜態變數
static
關鍵字用於建立獨立於類範例的變數。無論類的範例數有多少個,都只存在一個靜態變數副本。靜態變數也稱為類變數。區域性變數不能宣告為static
。
1.2. 靜態方法
static
關鍵字用於建立獨立於類範例的方法。
靜態方法不能使用作為類的物件的範例變數,靜態方法也叫作類方法。靜態方法從引數中獲取所有資料並從這些引數計算某些內容,而不參照變數。可以使用類名後跟一個點(.
)以及變數或方法的名稱來存取類變數或方法。
範例
static
修飾符用於建立類方法和變數,如下例所示 - public class InstanceCounter {
private static int numInstances = 0;
protected static int getCount() {
return numInstances;
}
private static void addInstance() {
numInstances++;
}
InstanceCounter() {
InstanceCounter.addInstance();
}
public static void main(String[] arguments) {
System.out.println("Starting with " + InstanceCounter.getCount() + " instances");
for (int i = 0; i < 500; ++i) {
new InstanceCounter();
}
System.out.println("Created " + InstanceCounter.getCount() + " instances");
}
}
執行上面範例程式碼,得到以下結果:
Started with 0 instances
Created 500 instances
2.1. final變數
final變數只能顯式地初始化一次,宣告為final
的參照變數永遠不能重新分配以參照不同的物件。但是,可以更改物件內的資料。 因此,可以更改物件的狀態,但不能更改參照。
對於變數,final
修飾符通常與static
一起使用,以使常數成為類變數。
範例
public class Test {
final int value = 10;
// 以下是宣告常數的範例:
public static final int BOXWIDTH = 6;
static final String TITLE = "Manager";
public void changeValue() {
value = 12; // 會出錯,不能重新賦值
}
}
2.2. final方法
任何子類都不能覆蓋final
方法。 如前所述,final
修飾符可防止在子類中修改方法。
宣告final
方法的主要目的是不讓其它人改變方法的內容。
範例
可以在類宣告中使用final
修飾符宣告方法,如下例所示 -
public class Test {
public final void changeName() {
// 方法主體
}
}
2.3. final類
使用宣告為final
的類的主要目的是防止類被子類化。 如果一個類被標記為final
,那麼這個類不能被其它類繼承。
範例
public final class Test {
// body of class
}
3.1. 抽象類
抽象(abstract
)類不能範例化。如果一個類宣告為抽象(abstract
),那麼唯一的目的是擴充套件該類。
一個類不能是同時是abstract
和final
(因為final
類不能被擴充套件)。 如果一個類包含抽象方法,那麼該類應該被宣告為abstract
。 否則,將丟擲編譯錯誤。
抽象類可以包含抽象方法以及普通方法。
範例
abstract class Caravan {
private double price;
private String model;
private String year;
public void getYear(String y){};// 這是一個普通方法
public abstract void goFast(); // 這是一個抽象方法
public abstract void changeColor();// 這是一個抽象方法
}
3.2. 抽象方法
抽象方法是在沒有任何實現的情況下宣告的方法。 方法體(實現)由子類提供。 抽象方法永遠不會是最終的或嚴格的。
擴充套件抽象類的任何類都必須實現超類的所有抽象方法,除非子類也是抽象類。
如果一個類包含一個或多個抽象方法,那麼該類必須宣告為abstract。 抽象類不需要包含抽象方法。
抽象方法以分號結尾。 範例:public abstract sample();
範例
public abstract class SuperClass {
abstract void m(); // 抽象方法
}
class SubClass extends SuperClass {
// 實現抽象方法
void m() {
// 實現程式碼.........
}
}
synchronized
關鍵字用於指示一次只能存取一個方法的方法。synchronized
修飾符可以應用於四個存取級別修飾符中的任何一個。
範例
public synchronized void showDetails() {
.......
}
範例變數標記為transient
,表示JVM在序列化包含它的物件時跳過特定變數。
此修飾符包含在建立變數的語句中,位於變數的類或資料型別之前。
範例
public transient int limit = 55; // will not persist
public int b; // will persist
volatile
修飾符用於讓JVM知道存取變數的執行緒必須始終將其自己的變數私有副本與記憶體中的主副本合併。
存取volatile
變數會同步主記憶體中變數的所有快取複製。 volatile
只能應用於範例變數,型別為private
。 volatile
物件參照可以為null
。
範例
public class MyRunnable implements Runnable {
private volatile boolean active;
public void run() {
active = true;
while (active) { // line 1
// some code here
}
}
public void stop() {
active = false; // line 2
}
}
通常,在一個執行緒(使用Runnable
開始的執行緒)中呼叫run()
,並從另一個執行緒呼叫stop()
。 如果在第1
行中使用了active
的快取值,那麼當在第2
行中將active
設定為false
時,迴圈可能不會停止。