JAVA面試題 淺析Java中的static關鍵字

Java螞蟻發表於2019-07-16

面試官Q1:請說說static關鍵字,你在專案中是怎麼使用的?

  • static 關鍵字可以用來修飾:屬性、方法、內部類、程式碼塊;

  • static 修飾的資源屬於類級別,是全體物件例項共享的資源;

  • 使用 static 修飾的屬性,靜態屬性是在類的載入期間初始化的,使用類名.屬性訪問

案例說明

①修飾成員變數

 package com.ant.param;
 public class StaticFieldDemo {
     public static void main(String[] args) {
         Foo f1 = new Foo();
         Foo f2 = new Foo();
         Foo f3 = new Foo();
         System.out.println(f1.id + " " + f2.id + " " + f3.id );
     }
 }
class Foo{
    int id;
}
執行結果如下:
0 0 0

上面的程式碼我們很熟悉,根據Foo構造出的每一個物件都是獨立存在的,儲存有自己獨立的成員變數,相互不會影響,他們在記憶體中的示意如下:

從上圖中可以看出,f1、f2和f3三個變數引用的物件分別儲存在記憶體中堆區域的不同地址中,所以他們之間相互不會干擾。物件的成員屬性都在這了,由每個物件自己儲存。f1.id、f2.id、f3.id相當於“每個人一個水杯”。

我們對上面的程式碼,做如下修改:

package com.ant.param;
 public class StaticFieldDemo {
     public static void main(String[] args) {
         Foo f1 = new Foo();
         Foo f2 = new Foo();
         Foo f3 = new Foo();
         System.out.println(f1.id + " " + f2.id + " " +
         f3.id + " " + Foo.i);
     }
}
class Foo{
    int id;
    static int i=0;
    public Foo(){
        id = i++;
    }
}
執行結果如下:
0 1 2 3

程式執行過程記憶體圖如下所示:

第 1 步:載入類

static修飾的變數在類載入期間初始化,且在方法區中分配,屬於執行緒共享區,所有的物件例項共享一份資料。

第 2步:繼續載入類

第 3步:繼續載入類

 

最終載入結果如上述三個步驟

 

②修飾成員方法

static的另一個作用,就是修飾成員方法。相比於修飾成員屬性,修飾成員方法對於資料的儲存上面並沒有多大的變化,因為我們從上面可以看出,方法本來就是存放在類的定義當中的(方法區)。static修飾成員方法最大的作用,就是可以使用"類名.方法名"的方式操作方法,避免了先要new出物件的繁瑣和資源消耗,我們可能會經常在幫助類中看到它的使用:

 package com.ant.param;
 
 public class StaticFieldDemo {
     private static void print(){
         System.out.println("hello");
     }
     public static void main(String[] args) {
         StaticFieldDemo.print();
     }
}

③修飾靜態程式碼塊

靜態程式碼塊是在類載入期間執行的程式碼塊,由於類只載入一次,所以靜態程式碼塊只執行一次!靜態程式碼塊用途很常見,一般用來在類載入以後初始化一些靜態資源時候使用。如:載入配置檔案等

package com.ant.param;
 
 public class StaticBlockDemo {
     public static void main(String[] args) {
         Foo foo = new Foo();
     }
 }
 
 class Foo{
    //程式碼塊,在建立物件的時候執行,使用很少,和構造器差不多
    {
        System.out.println("建立物件了!");
    }
    //靜態程式碼塊,在類載入期間執行,用於載入配置檔案或者其他資訊等
    static{
        System.out.println("類載入了!");
    }
    public Foo(){
        System.out.println("呼叫了構造器!");
    }
}

靜態塊用法:將多個類成員放在一起初始化,使得程式更加規整,對理解物件的初始化過程非常關鍵;

在我的印象中,這些問題一般初中級Java工程師會被問到,都是很常規的面試題,您會了嗎?

  

相關文章