static對於我們這些初學者在編寫程式碼和閱讀程式碼是一個難以理解的關鍵字,也是大量公司面試題最喜歡考的之一。下面我就來就先講述一下static關鍵字的用法和我們初學者容易誤解的地方。

  1. static關鍵字的用途
  2. static常見誤區
  3. static常見面試題

若有不正之處,敬請諒解歡迎批評指教,共同進步,最近才更新一些,作為初學者,我覺得還是很有必要的。

參考   http://www.cnblogs.com/dolphin0520/p/3799052.html

一、static關鍵字的用途

在《Java程式設計思想》P86頁有這樣一段話:

  “static方法就是沒有this的方法。在static方法內部不能呼叫非靜態方法,反過來是可以的。而且可以在沒有建立任何物件的前提下,僅僅通過類本身來呼叫static方法。這實際上正是static方法的主要用途。”

    方便在沒有建立物件的情況下來進行呼叫(方法/變數)。

  很顯然,被static關鍵字修飾的方法或者變數不需要依賴於物件來進行訪問,只要類被載入了,就可以通過類名去進行訪問。

  static可以用來修飾類的成員方法、類的成員變數,另外可以編寫static程式碼塊來優化程式效能

1)static方法

  static方法一般稱作靜態方法,由於靜態方法不依賴於任何物件就可以進行訪問,因此對於靜態方法來說,是沒有this的,因為它不依附於任何物件,既然都沒有物件,就談不上this了。並且由於這個特性,在靜態方法中不能訪問類的非靜態成員變數和非靜態成員方法,因為非靜態成員方法/變數都是必須依賴具體的物件才能夠被呼叫。

  但是要注意的是,雖然在靜態方法中不能訪問非靜態成員方法和非靜態成員變數,但是在非靜態成員方法中是可以訪問靜態成員方法/變數的。舉個簡單的例子:

 package test3;

 public class testst {
private static String str1="static 變數";
private String str2="常量";
public void print1(){
System.out.println(str1);
System.out.println(str2);
print2();
}
public static void print2(){
System.out.println(str1);
//System.out.println(str2);靜態方法只能
//print1();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new testst().print1();
} }
static 變數
常量
static 變數

而對於非靜態成員方法,它訪問靜態成員方法/變數顯然是毫無限制的。

  因此,如果說想在不建立物件的情況下呼叫某個方法,就可以將這個方法設定為static。我們最常見的static方法就是main方法,至於為什麼main方法必須是static的,現在就很清楚了。因為程式在執行main方法的時候沒有建立任何物件,因此只有通過類名來訪問。

  另外記住,即使沒有顯示地宣告為static,類的構造器實際上也是靜態方法。

2)static變數

  static變數也稱作靜態變數,靜態變數和非靜態變數的區別是:靜態變數被所有的物件所共享,在記憶體中只有一個副本,它當且僅當在類初次載入時會被初始化。而非靜態變數是物件所擁有的,在建立物件的時候被初始化,存在多個副本,各個物件擁有的副本互不影響。

  static成員變數的初始化順序按照定義的順序進行初始化。

3)static程式碼塊

  static關鍵字還有一個比較關鍵的作用就是 用來形成靜態程式碼塊以優化程式效能。static塊可以置於類中的任何地方,類中可以有多個static塊。在類初次被載入的時候,會按照static塊的順序來執行每個static塊,並且只會執行一次。

二、static關鍵字的誤區

1.static關鍵字會改變類中成員的訪問許可權嗎?

  有些初學的朋友會將java中的static與C/C++中的static關鍵字的功能混淆了。在這裡只需要記住一點:與C/C++中的static不同,Java中的static關鍵字不會影響到變數或者方法的作用域。在Java中能夠影響到訪問許可權的只有private、public、protected(包括包訪問許可權)這幾個關鍵字。看下面的例子就明白了:

 package test3;

 public class testst {

     public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(person.name);
System.out.println(person.age);
}
}
class person{
public static String name="laoli";
private static int age=16;
}

紅色 背景色會報錯,提示錯誤"Person.age 不可視",這說明static關鍵字並不會改變變數和方法的訪問許可權。

2.能通過this訪問靜態成員變數嗎?

在這裡永遠要記住一點:靜態成員變數雖然獨立於物件,但是不代表不可以通過物件去訪問,所有的靜態方法和靜態變數都可以通過物件訪問(只要訪問許可權足夠)。

3.static能作用於區域性變數麼?

在C/C++中static是可以作用域區域性變數的,但是在Java中切記:static是不允許用來修飾區域性變數。不要問為什麼,這是Java語法的規定。

三、static關鍵字的面試題

1.下面這段程式碼的輸出結果是什麼?

 package test3;

 public class testst extends Base{
static{
System.out.println("test static");
} public testst(){
System.out.println("test constructor");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new testst();
}
}
class Base{ static{
System.out.println("base static");
} public Base(){
System.out.println("base constructor");
}
}
base static
test static
base constructor
test constructor

至於為什麼是這個結果,我們先不討論,先來想一下這段程式碼具體的執行過程,在執行開始,先要尋找到main方法,因為main方法是程式的入口,但是在執行main方法之前,必須先載入testst類,而在載入testst類的時候發現Test類繼承自Base類,因此會轉去先載入Base類,在載入Base類的時候,發現有static塊,便執行了static塊。在Base類載入完成之後,便繼續載入testst類,然後發現testst類中也有static塊,便執行static塊。在載入完所需的類之後,便開始執行main方法。在main方法中執行new testst()的時候會先呼叫父類的構造器,然後再呼叫自身的構造器。因此,便出現了上面的輸出結果。

另外,static塊可以出現類中的任何地方(只要不是方法內部,記住,任何方法內部都不行),並且執行是按照static塊的順序執行的。