1. 程式人生 > >[java]static關鍵字的四種用法和void的用法

[java]static關鍵字的四種用法和void的用法

void關鍵字表示函式沒有返回結果,是java中的一個關鍵字。

Void作為函式的返回結果表示函式返回null(除了null不能返回其它型別)。

在java的關鍵字中,staticfinal是兩個我們必須掌握的關鍵字。不同於其他關鍵字,他們都有多種用法,而且在一定環境下使用,可以提高程式的執行效能,優化程式的結構。下面我們先來了解一下static關鍵字及其用法。

static關鍵字

1.修飾成員變數

在我們平時的使用當中,static最常用的功能就是修飾類的屬性和方法,讓他們成為類的成員屬性和方法,我們通常將用static修飾的成員稱為類成員或者靜態成員,這句話挺起來都點奇怪,其實這是相對於物件的屬性和方法來說的。請看下面的例子:(未避免程式太過臃腫,暫時不管訪問控制)

public class Person {
    String name;
    int age;
    
    public String toString() {
        return "Name:" + name + ", Age:" + age;
    }
    
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.name = "zhangsan";
        p1.age = 10;
        Person p2 = new Person();
        p2.name = "lisi";
        p2.age = 12;
        System.out.println(p1);
        System.out.println(p2);
    }
    /**Output
     * Name:zhangsan, Age:10
     * Name:lisi, Age:12
     *///~
}

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


從上圖中可以看出,p1和p2兩個變數引用的物件分別儲存在記憶體中堆區域的不同地址中,所以他們之間相互不會干擾。但其實,在這當中,我們省略了一些重要資訊,相信大家也都會想到,物件的成員屬性都在這了,由每個物件自己儲存,那麼他們的方法呢?實際上,不論一個類建立了幾個物件,他們的方法都是一樣的:

從上面的圖中我們可以看到,兩個Person物件的方法實際上只是指向了同一個方法定義。這個方法定義是位於記憶體中的一塊不變區域(由jvm劃分),我們暫稱它為靜態儲存區。這一塊儲存區不僅存放了方法的定義,實際上從更大的角度而言,它存放的是各種類的定義,當我們通過new來生成物件時,會根據這裡定義的類的定義去建立物件。多個物件僅會對應同一個方法,這裡有一個讓我們充分信服的理由,那就是不管多少的物件,他們的方法總是相同的,儘管最後的輸出會有所不同,但是方法總是會按照我們預想的結果去操作,即不同的物件去呼叫同一個方法,結果會不盡相同。

我們知道,static關鍵字可以修飾成員變數和方法,來讓它們變成類的所屬,而不是物件的所屬,比如我們將Person的age屬性用static進行修飾,結果會是什麼樣呢?請看下面的例子:


public class Person {
    String name;
    static int age;
    
    /* 其餘程式碼不變... */

    /**Output
     * Name:zhangsan, Age:12
     * Name:lisi, Age:12
     *///~
}

我們發現,結果發生了一點變化,在給p2的age屬性賦值時,干擾了p1的age屬性,這是為什麼呢?我們還是來看他們在記憶體中的示意:

我們發現,給age屬性加了static關鍵字之後,Person物件就不再擁有age屬性了,age屬性會統一交給Person類去管理,即多個Person物件只會對應一個age屬性,一個物件如果對age屬性做了改變,其他的物件都會受到影響。我們看到此時的age和toString()方法一樣,都是交由類去管理。

雖然我們看到static可以讓物件共享屬性,但是實際中我們很少這麼用,也不推薦這麼使用。因為這樣會讓該屬性變得難以控制,因為它在任何地方都有可能被改變。如果我們想共享屬性,一般我們會採用其他的辦法:

public class Person {
    private static int count = 0;
    int id;
    String name;
    int age;
    
    public Person() {
        id = ++count;
    }
    
    public String toString() {
        return "Id:" + id + ", Name:" + name + ", Age:" + age;
    }
    
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.name = "zhangsan";
        p1.age = 10;
        Person p2 = new Person();
        p2.name = "lisi";
        p2.age = 12;
        System.out.println(p1);
        System.out.println(p2);
    }
    /**Output
     * Id:1, Name:zhangsan, Age:10
     * Id:2, Name:lisi, Age:12
     *///~
}

上面的程式碼起到了給Person的物件建立一個唯一id以及記錄總數的作用,其中count由static修飾,是Person類的成員屬性,每次建立一個Person物件,就會使該屬性自加1然後賦給物件的id屬性,這樣,count屬性記錄了建立Person物件的總數,由於count使用了private修飾,所以從類外面無法隨意改變。

2.修飾成員方法

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


public class PrintHelper {

    public static void print(Object o){
        System.out.println(o);
    }
    
    public static void main(String[] args) {
        PrintHelper.print("Hello world");
    }
}

上面便是一個例子(現在還不太實用),但是我們可以看到它的作用,使得static修飾的方法成為類的方法,使用時通過“類名.方法名”的方式就可以方便的使用了,相當於定義了一個全域性的函式(只要匯入該類所在的包即可)。不過它也有使用的侷限,一個static修飾的類中,不能使用非static修飾的成員變數和方法,這很好理解,因為static修飾的方法是屬於類的,如果去直接使用物件的成員變數,它會不知所措(不知該使用哪一個物件的屬性)。

3.靜態塊

在說明static關鍵字的第三個用法時,我們有必要重新梳理一下一個物件的初始化過程。以下面的程式碼為例:

package com.dotgua.study;

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 main(String[] args) {
        Person p1 = new Person("p1初始化");
    }
    /**Output
     * static成員book2成員變數初始化
     * static成員book4成員變數初始化
     * book1成員變數初始化
     * book3成員變數初始化
     * p1初始化
     *///~
}

 上面的例子中,Person類中組合了四個Book成員變數,兩個是普通成員,兩個是static修飾的類成員。我們可以看到,當我們new一個Person物件時,static修飾的成員變數首先被初始化,隨後是普通成員,最後呼叫Person類的構造方法完成初始化。也就是說,在建立物件時,static修飾的成員會首先被初始化,而且我們還可以看到,如果有多個static修飾的成員,那麼會按照他們的先後位置進行初始化。

實際上,static修飾的成員的初始化可以更早的進行,請看下面的例子:

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修飾的類成員,在程式執行過程中,只需要初始化一次即可,不會進行多次的初始化。

回顧了物件的初始化以後,我們再來看static的第三個作用就非常簡單了,那就是當我們初始化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初始化
     *///~
}

我們將上一個例子稍微做了一下修改,可以看到,結果沒有二致。

4.靜態導包

 相比於上面的三種用途,第四種用途可能瞭解的人就比較少了,但是實際上它很簡單,而且在呼叫類方法時會更方便。以上面的“PrintHelper”的例子為例,做一下稍微的變化,即可使用靜態導包帶給我們的方便:

/* PrintHelper.java檔案 */
package com.dotgua.study;

public class PrintHelper {

    public static void print(Object o){
        System.out.println(o);
    }
}
/* App.java檔案 */
import static com.dotgua.study.PrintHelper.*;

public class App 
{
    public static void main( String[] args )
    {
        print("Hello World!");
    }
    /**Output
     * Hello World!
     *///~
}


上面的程式碼來自於兩個java檔案,其中的PrintHelper很簡單,包含了一個用於列印的static方法。而在App.java檔案中,我們首先將PrintHelper類匯入,這裡在匯入時,我們使用了static關鍵字,而且在引入類的最後還加上了“.*”,它的作用就是將PrintHelper類中的所有類方法直接匯入。不同於非static匯入,採用static匯入包後,在不與當前類的方法名衝突的情況下,無需使用“類名.方法名”的方法去呼叫類方法了,直接可以採用"方法名"去呼叫類方法,就好像是該類自己的方法一樣使用即可。

總結

static是java中非常重要的一個關鍵字,而且它的用法也很豐富,主要有四種用法:

  1. 用來修飾成員變數,將其變為類的成員,從而實現所有物件對於該成員的共享;
  2. 用來修飾成員方法,將其變為類方法,可以直接使用“類名.方法名”的方式呼叫,常用於工具類;
  3. 靜態塊用法,將多個類成員放在一起初始化,使得程式更加規整,其中理解物件的初始化過程非常關鍵;
  4. 靜態導包用法,將類的方法直接匯入到當前類中,從而直接使用“方法名”即可呼叫類方法,更加方便。

相關推薦

Java static關鍵字用法

static關鍵字,是我們在java開發中必須掌握的關鍵字之一,不同的關鍵字有著不同的作用,在適合的環境下運用可以,可以提高程式的執行效能,優化程式的結構。 靜態成員的使用“類名.靜態成員”

[java]static關鍵字用法void用法

void關鍵字表示函式沒有返回結果,是java中的一個關鍵字。Void作為函式的返回結果表示函式返回null(除了null不能返回其它型別)。在java的關鍵字中,static和final是兩個我們必須掌握的關鍵字。不同於其他關鍵字,他們都有多種用法,而且在一定環境下使用,可

[java]static關鍵字用法

在java的關鍵字中,static和final是兩個我們必須掌握的關鍵字。不同於其他關鍵字,他們都有多種用法,而且在一定環境下使用,可以提高程式的執行效能,優化程式的結構。下面我們先來了解一下static關鍵字及其用法。 static關鍵字 1.修飾成員變數 在我們平時的使用當中,static最常用的功能就是

java初學 面向物件二 static關鍵字 封裝、繼承多型

static關鍵字 1:如果沒有static會怎樣? 1:定義Person類 1:姓名、年齡、國籍,說話行為 2:多個構造,過載形式體現 2:中國人的國籍都是確定的 1:國籍可以進行顯示初始化 class Person {

Java中的引用以及ReferenceQueueWeakHashMap的使用示例

簡介: 本文主要介紹JAVA中的四種引用: StrongReference(強引用)、SoftReferenc(軟引用)、WeakReferenc(弱引用)、PhantomReference(虛引用)的作用。同時我們還將介紹ReferenceQueue和WeakHashMap的功能和使用示例。 歡迎探討,如

(轉)java向MySQL插入當前時間的方式java時間日期格式化的幾方法(案例說明)

轉載地址  https://www.cnblogs.com/zhaotiancheng/p/6413067.html 資料庫操作經常會用到時間,例如start_time,end_time,(在資料庫中是datetime型別,) 對應關係 mys

java 執行緒池詳解及執行緒池用法介紹

java 執行緒池詳解      Executor框架是一種將執行緒的建立和執行分離的機制。它基於Executor和ExecutorService介面,及這兩個介面的實現類ThreadPoolExecutor展開,Executor有一個內部執行緒池,並提供了將任務傳遞到池中

java之中的訪問許可權子類如何繼承父類特性

Public:對所有類可見 Protected:對同一包中的類,和子類可見 Private:僅對類本身可見         Default:對同一包中的類可見 為了理解方便,可見的意思也就是可以使用這個特性(域,方法,類),對子類可見就是子類也具有這些特性。但是繼承的時候,

Java併發的風味:Thread、Executor、ForkJoinActor

這篇文章討論了Java應用中並行處理的多種方法。從自己管理Java執行緒,到各種更好幾的解決方法,Executor服務、ForkJoin 框架以及計算中的Actor模型。 Java併發程式設計的4種風格:Threads,Executors,ForkJoin和Actors 我們生

Java-引用ReferenceQueue簡述

熟悉Java的四種引用和ReferenceQueue,可以幫助解決快取和記憶體洩漏等問題。 Reference GC只清理物件所佔的記憶體,如DB、檔案等資源需要手動清理。 Reference決定了它所指向的物件的生命週期,從而決定了記憶體的使用量

Java集合系列】HashSetLinkedHashSet解析

inpu skin lam 繼承 depend try put args port 2017-07-29 16:58:13 一、簡介 1、Set概念 Set可以理解為集合,非常類似數據概念中的集合,集合三大特征:1、確定性;2、互異性;3、無序性,因此Set實現類也有類似的

java static 關鍵字

相對 調用 加載類 stat county 固定 str sta 靜態塊 可以修飾變量和方法。 修飾變量 加載類的時候分配內存空間。 相對於整個類來說,變量有固定,單獨的內存空間,是屬於整個類的,也就是“類變量”。非static修飾的變量是,相對於對象存在,是屬於對象(成

Java Static關鍵字詳解

會有 java 非靜態屬性 指向 style 關於 區域 當前 為什麽 先思考兩個問題: 1.為什麽要使用Static關鍵字? 2.加了Static關鍵字修飾後會有什麽不同? Static 一.為什麽要使用Static關鍵字? 這裏摘錄一下《Java編程思想(第四版)

Java中的引用

hab clear 不足 生命周期 特點 目的 bject 存在 增強   在JDK 1.2以前的版本中,若一個對象不被任何變量引用,那麽程序就無法再使用這個對象。也就是說,只有對象處於可觸及(reachable)狀態,程序才能使用它。從JDK 1.2版本開始,把對象的引用

Spring(七)Spring中的增強顧問

print .com ima stack schema reflect 環繞增強 ace classpath Spring中的四種增強有那四種? 前置增強 後置增強 環繞增強 異常增強 先編寫接口和實體類 ISomeService和SomeServiceImpl

Sping(七)Sping增強顧問

實體 urn oca lB 之前 log exc -- title 前置增強 後置增強 環繞增強 異常增強 先編寫接口和實體類 ISomeService和SomeServiceImpl package demo10; /** * Created by m

java static關鍵字修飾方法

java static關鍵字修飾方法 1.java static關鍵字修飾方法的特性 2.注意要點 1.java static關鍵字修飾方法的特性 隨著類的載入而載入,在記憶體中也是獨一份 可以直接通過“

Java: HashMap、HashTable、LinkedHashMapTreeMap用法區別

Java為資料結構中的對映定義了一個介面java.util.Map,它有四個實現類,分別是HashMap、HashTable、LinkedHashMap和TreeMap。本節例項主要介紹這4中例項的用法和區別。 關鍵技術剖析: Map用於儲存鍵值對,根據鍵得到值,因此不允許鍵重複,值可以重複。 l

java陣列的拷貝方式

拷貝陣列方式 深拷貝/淺拷貝 是否產生新的物件 備註 for迴圈拷貝 淺拷貝 否 拷貝速度最慢 clone拷貝陣列

java程式設計入門2 java中的訪問許可權控制

在java中提供了四種訪問許可權控制:預設訪問許可權(包訪問許可權),public,private以及protected 只有預設訪問許可權(包訪問許可權)和public能用來修飾類(不包括內部類) 修飾變數和方法這四種許可權均可 1.public 修飾類表示該類對其他所有類可見 修飾一個類的變數和