Java提供了許多非訪問修飾符來實現許多其他功能。
- static修飾符用於創建類方法和變數。
- final修飾符用於完成類,方法和變數的實現。
- abstract修飾符用於創建抽象類和方法。
- synchronized和- volatile修飾符,用於線程。
下麵來逐個瞭解和學習這些非訪問修飾符。
1. static修飾符
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. final修飾符
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. abstract飾符
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() {
      // 實現代碼.........
   }
}
4. synchronized修飾符
synchronized關鍵字用於指示一次只能訪問一個方法的方法。synchronized修飾符可以應用於四個訪問級別修飾符中的任何一個。
示例
public synchronized void showDetails() {
   .......
}
5. transient修飾符
實例變數標記為transient,表示JVM在序列化包含它的對象時跳過特定變數。
此修飾符包含在創建變數的語句中,位於變數的類或數據類型之前。
示例
public transient int limit = 55;   // will not persist
public int b;   // will persist
6. volatile修飾符
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時,迴圈可能不會停止。
