1. 程式人生 > >Java Static關鍵字詳解

Java Static關鍵字詳解

會有 java 非靜態屬性 指向 style 關於 區域 當前 為什麽

先思考兩個問題:

1.為什麽要使用Static關鍵字?

2.加了Static關鍵字修飾後會有什麽不同?

Static

一.為什麽要使用Static關鍵字?

這裏摘錄一下《Java編程思想(第四版)》裏關於static關鍵字的一段原話:(P29)通常來說,當創建類時,就是在描述那個類的對象的外觀與行為。除非用new創建那個對象,否則,實際上並未獲得任何對象。執行new來創建對象的時候,數據存儲空間才被分配,其方法才供外界調用。有兩種情形用上述方法是無法解決的。一種情形是,只想為某特定域分配單一存儲空間,而不去考慮究竟要創建多少個對象,甚至根本不需要創建任何對象。另一種情形是,希望某個方法不與包含他的類的任何對象關聯在一起。也就是說,即使沒有創建對象,也能夠調用方法

。簡單來說,static的主要目的就是創建獨立於具體對象的域變量與方法。

二.加了Static關鍵字修飾會有什麽不同?

1.this不能調用被static修飾的屬性字段。

因為被static修飾的會在類加載的時候初始化,被稱為類級變量(屬於類);而類的實例是在運行的時候初始化,屬於對象級變量(屬於對象)。

this是指當前對象的實例,super是指父類對象的實例。this(super)不能調用被static修飾的屬性字段的原因:jvm有類加載器,第一次加載時執行static域,jvm會專門劃分一個內存區域給static程序塊,所以什麽時候都可以調用這個被static修飾的屬性字段或者方法,屬於類。this指針是指向類的對象,在實例化對象時候jvm會在堆區分配給一個具體對象,this指向該對象。所以在靜態方法中不能調用非靜態屬性或者方法

,如果在靜態方法中使用this關鍵字,則this無法指向合適的對象。(通俗一點的話:即jvm的類加載機制決定了加載靜態會先與非靜態,即加載靜態的時候非靜態屬性和方法都不存在)

2.static修飾屬性和方法

1.static修飾屬性時候,即所有該類對象共享一份存儲空間。

public class StaticTest {
    public static int staticA;
    public int A;
    
    public static void main(String[] args){
       StaticTest test;
       StaticTest A1
=new StaticTest(); StaticTest A2=new StaticTest(); A1.staticA++; A2.staticA++; A1.A++; A2.A++; System.out.println("StaticAInfo:"+A1.staticA+" "+A2.staticA); System.out.println("AInfo"+A1.A+" "+A2.A); } } /** 運行結果 * StaticAInfo:2 2 * AInfo1 1 **/

即static修飾的不是某個具體對象所有,而是該類所有對象共有的,StaticTest.staticA只有一份存儲空間。

2.static修飾方法時候,類和對象都能調用該方法,沒有被static修飾的方法只能被實例化對象調用。

public class StaticTest {
    public static void staticTest(){
        
    }    
    public void test(){
        
    }
      
    public static void main(String[] args){
       StaticTest.staticTest();
       //StaticTest.test();  該調用是錯誤的
       StaticTest test=new StaticTest();
       test.staticTest();
       test.test();
    }
}

static修飾成員方法最大的作用,就是可以使用"類名.方法名"的方式操作方法,避免了先要new出對象的繁瑣和資源消耗,一個static修飾的類中,不能使用非static修飾的成員變量和方法,這很好理解,因為static修飾的方法是屬於類的,如果去直接使用對象的成員變量,它會不知所措(不知該使用哪一個對象的屬性)。

static修飾成員方法的時候最大的好處是可以節省new一個對象的開銷,即可以直接通過類來調用方法。

3.static修飾內部類

一般用的比較少只能用來修飾內部類,一個static修飾的內部類中,不能使用非static修飾的成員變量和方法,這很好理解,因為static修飾的方法是屬於類的,如果去直接使用對象的成員變量,它會不知所措(不知該使用哪一個對象的屬性)。

4.靜態塊

class Book{
    public Book(String msg) {
        System.out.println(msg);
    }
}

public class Person {

    Book book1 = new Book("book1成員變量初始化");
    static Book book2 = new Book("static成員book2成員變量初始化");
    
    public Person(String msg) {
        System.out.println(msg);
    }
    
    Book book3 = new Book("book3成員變量初始化");
    static Book book4 = new Book("static成員book4成員變量初始化");
    
    public static void funStatic() {
        System.out.println("static修飾的funStatic方法");
    }
    
    public static void main(String[] args) {
        Person.funStatic();
        System.out.println("****************");
        Person p1 = new Person("p1初始化");
    }
    /**Output
     * static成員book2成員變量初始化
     * static成員book4成員變量初始化
     * static修飾的funStatic方法
     * ***************
     * book1成員變量初始化
     * book3成員變量初始化
     * p1初始化
     *///~
}

在上面的例子中我們可以發現兩個有意思的地方,第一個是當我們沒有創建對象,而是通過類去調用類方法時,盡管該方法沒有使用到任何的類成員,類成員還是在方法調用之前就初始化了,這說明,當我們第一次去使用一個類時,就會觸發該類的成員初始化。第二個是當我們使用了類方法,完成類的成員的初始化後,再new該類的對象時,static修飾的類成員沒有再次初始化,這說明,static修飾的類成員,在程序運行過程中,只需要初始化一次即可,不會進行多次的初始化

class Book{
    public Book(String msg) {
        System.out.println(msg);
    }
}

public class Person {

    Book book1 = new Book("book1成員變量初始化");
    static Book book2;
    
    static {
        book2 = new Book("static成員book2成員變量初始化");
        book4 = new Book("static成員book4成員變量初始化");
    }
    
    public Person(String msg) {
        System.out.println(msg);
    }
    
    Book book3 = new Book("book3成員變量初始化");
    static Book book4;
    
    public static void funStatic() {
        System.out.println("static修飾的funStatic方法");
    }
    
    public static void main(String[] args) {
        Person.funStatic();
        System.out.println("****************");
        Person p1 = new Person("p1初始化");
    }
    /**Output
     * static成員book2成員變量初始化
     * static成員book4成員變量初始化
     * static修飾的funStatic方法
     * ***************
     * book1成員變量初始化
     * book3成員變量初始化
     * p1初始化
     *///~
}

Java Static關鍵字詳解