Java關於static的做用

概述

只要是有學過Java的都必定知道static,也必定能多多少少說出一些做用和注意事項。若是已經對static瞭如指掌的請點擊關閉按鈕,看下去也只是浪費您寶貴時間而已。這篇隨筆只是我的的習慣總結。java

爲何須要static?

有時候咱們並不想去new一個對象,只是單純的想要調用一個函數,而且但願這個函數不會與包含它的類的其餘對象有所關聯。說得通俗點,即便沒有建立對象,也能經過類自己來調用函數。編程

static靜態變量

被static修飾的變量屬於類變量,經過字面意思就說明了這個變量的歸屬(類),與之相對的是沒有被static修飾的成員變量,也稱爲實例變量,說明這個變量是屬於某個具體的對象。函數

public class StaticDemo
{
    private static int i = 50;

    private int j = 60;

    public static void main(String[] args) {
        StaticDemo staticDemo = new StaticDemo();
        StaticDemo staticDemo1 = new StaticDemo();
        //即便建立兩個對象,也都指向同一存儲空間
        System.out.println(staticDemo.i);
        System.out.println(staticDemo1.i);
        //改變值
        staticDemo.i = 52;
        System.out.println(staticDemo1.i);
        staticDemo.j = 65;
        staticDemo1.j = 70;
        System.out.println(staticDemo.j);
        System.out.println(staticDemo1.j);
    }

}

輸出測試

50
50
52 65 70

經過上面的實例,咱們很快看出他們的區別this

  1. 靜態變量是屬於類的,只有一份存儲空間,是類之間共享的,牽一髮而動全身,一處變,到處變。
  2. 實例變量屬於實例對象,建立幾回對象,就有幾份的成員變量(拷貝)。

static修飾的靜態函數

說到靜態函數,就不得不提Java另外一個關鍵詞this,指的是當前的引用。意思是調用這個函數的對象,這意味着和static修飾的函數水火不容。被static修飾的函數,不能出現this關鍵字,不然便會報錯。spa

去掉this,分別調用i或者j,會發現靜態函數調用非靜態資源時出錯。這是爲何?從JVM加載機制角度來講,靜態資源(被staitc修飾)是類在初始化的時候就加載的,而非靜態資源是new的時候加載的。類的初始化是早於new的,加載了say()的函數時,它並不認識 j 這個成員變量,但對於非靜態函數來講,當它加載時,靜態資源已經加載完畢,因此它是認識 i 這個靜態資源的。咱們總結一下static修飾函數時的特色code

  1. 靜態函數不能引用非靜態資源;
  2. 非靜態函數能夠引用靜態資源;
  3. 靜態函數能夠相互調用(只要引入所在包便可);
  4. 靜態函數沒有this,由於它不依附於任何對象。

如今,咱們也能知道main函數爲何必須是static的,由於程序在執行main函數時候,沒有建立任何對象,只是經過類名來訪問。對象

構造函數是否是靜態函數?

《Java編程思想》提到「即便沒有顯示地使用static關鍵字,構造器實際上也是靜態方法」。我至今不能確認構造器是否是靜態函數,我的更偏向於不是。緣由待會再闡述,先看個實例blog

public class StaticTest
{
    private static int i;

    private int j;

    public StaticTest(int i,int j)
{
this.i = i; this.j = j;
     say1() }
public void say1() { System.out.println("you age is" + i); System.out.println("you age is" + j); } public static void main(String[] args) { StaticTest staticTest = new StaticTest(4,5); StaticTest staticTest1 = new StaticTest(10,69); System.out.println(staticTest.i); System.out.println(staticTest.j); System.out.println(staticTest1.i); System.out.println(staticTest1.j); } }

輸出資源

you age is4
you age is5
you age is10
you age is69
10
5
10
69

實例中,確實改變了 i 的值,也符合靜態資源的定義,只有一份存儲空間。但構造器裏用了this,與我前文所說的static屬於類,不屬於任何對象,this屬於當前引用對象互相矛盾,而且構造函數還能夠調用實例函數。一臉懵逼,這也是讓我感到困惑而且認爲構造函數不是靜態函數的地方。若有周知,留言解惑,感謝。

靜態塊與非靜態塊

private static int i;  

static { i = 5; }

靜態塊是static的重要應用之一,無函數名、做用域、返回值以及參數,靜態代碼塊與靜態變量和靜態函數同樣,不論類被調用多少次,該區域代碼只在類初始化時第一次時執行一次,而且嚴格按照靜態資源的定義順序執行加載,與靜態函數區別在於一個主動一個被動。

  {
        System.out.println("我是靜態塊.");
  }

非靜態塊,一樣無函數名,做用域,返回值以及參數,非靜態代碼塊會在每次類被調用或者被實例化時執行。

實例

public class StaticTest extends Father
{
    public StaticTest()
    {
        System.out.println("我是StaticTest的構造函數");
    }

    {
        System.out.println("我是StaticTest的非靜態塊");
    }

    static
    {
        System.out.println("我是StaticTest的靜態塊");
    }

    public static void main(String[] args)
    {
        new StaticTest();
        new StaticTest();
    }
}

class Father
{
    public Father()
    {
        System.out.println("我是Father構造函數");
    }

    {
        System.out.println("我是Father非靜態塊1");
    }

    {
        System.out.println("我是Father非靜態塊2");
    }

    static
    {
        System.out.println("我是Father靜態塊");
    }

}

輸出

我是Father靜態塊
我是StaticTest的靜態塊
我是Father非靜態塊1
我是Father非靜態塊2
我是Father構造函數
我是StaticTest的非靜態塊
我是StaticTest的構造函數
我是Father非靜態塊1
我是Father非靜態塊2
我是Father構造函數
我是StaticTest的非靜態塊
我是StaticTest的構造函數

加載順序 :父類靜態塊 > 子類靜態塊 > 父類非靜態塊 > 父類構造函數 > 子類非靜態塊 > 子類構造函數

靜態代碼塊以及非靜態代碼塊都會在構造函數前執行,首次訪問時,靜態代碼塊會在非靜態代碼塊前執行。

改變main函數

public static void main(String[] args)
{
        
}

輸出

我是Father靜態塊
我是StaticTest的靜態塊

靜態代碼塊在類加載時自動執行,非靜態代碼塊是在建立對象時自動執行的代碼,不建立對象不執行該類的非靜態代碼塊。

靜態導入

靜態導入是jdk5引入的新特性,有時咱們在實際應用中,並不須要整個jar包都導入,而只是想使用某部分函數。提升代碼的閱讀性,更好的理解程序。

import static java.lang.System.out;

public class StaticTest
{
    public static void main(String[] args)
    {
        out.println("import static測試");
     System.out.println("import static測試");
    } 
}

輸出

import static測試
import static測試

會發現,二者輸出是沒有區別的,可是咱們少寫了System.   雖然容許這麼使用,但在實際開發中,我不多發現有同事這麼作,主要是不利於理解,但好處是若是頻繁用這個類,能夠少不少的類名。

===============================================================

如發現錯誤,請及時留言,lz及時修改,避免誤導後來者。感謝!!!

相關文章
相關標籤/搜索