1. 程式人生 > >Java的static和final關鍵字的用法

Java的static和final關鍵字的用法

and logs png 大寫 內存地址 imp 自己 普通 字母

static關鍵字的用法

  static的意思是“’靜態的”,在java裏面可用於修飾屬性和方法。

  static關鍵字的應用應註意以下幾種情形:  

    1.static作用於某個字段,一個static字段對每個類來說只有一份存儲空間,而非static字段是每個對象有一份存儲空間。

    2.static作用於方法的重要用法是不需要創建任何對象直接調用該static方法,這對於main()方法很重要。

    3.static不能應用於局部變量。

    4.Java中禁止使用全局方法,所以引入static方法通過類本身來直接調用。

package cn.wangze.test;

class Demo{ public static int i = 19; } public class staticDemo { private static Demo demo1 = new Demo(); private static Demo demo2 = new Demo(); public static void main(String[] args){ System.out.println(Demo.i); //19 System.out.println(demo1.i); //19 System.out.println(demo2.i); //
19 demo1.i++; System.out.println(Demo.i); //20 System.out.println(demo1.i); //20 System.out.println(demo2.i); //20 Demo.i++; System.out.println(Demo.i); //21 System.out.println(demo1.i); //21 System.out.println(demo2.i); //21
} }

  上面程序的輸出結果驗證了上面兩條,帶有static關鍵字的數據在內存中占有一塊固定內存地址,你可以用類名直接調用,也可以創建對象來調用,推薦ClassName.method()來調用。當我們改變它的值,任何地方的調用也會隨之改變。

  Java系統自帶的Math、UUID、Class等常用的工具類就是用的這種方式。

 為什麽要將方法和變量都寫成靜態的。
 因為,這些方法我只是想調用一下,不需要牽扯工具類中的任何屬性和變量,所以,我就沒有必要實例化了(new)。既然不需要實例化了,那麽就用靜態就行了。

技術分享

  你也可以在實際項目中根據業務需求來聲明自己的工具類,只需要加入static關鍵字,引入該類後使用類名.方法名()調用即可。

  需要註意的一點是,類的加載和初始化過程中,帶有static的數據會最先加載並調用,其次是構造器的加載,最後才是普通成員變量和方法的加載。

final關鍵字的用法

  final意味著"不可改變的",一般應用於數據、方法和類。

final數據

    當數據是基本類型時,意味著這是一個永不改變的編譯時常量,一個在運行時被初始化的值,你不希望它改變。

    當數據是引用類型時,用static和final修飾表示這是只占據一塊不能改變的內存空間。

    有一條約定成俗的規定是使用stati和final修飾的變量即編譯期常量應該用全部大寫字母表示,例如:

package cn.wangze.test;

import java.util.*;

class Value{
    int i;
    public Value(int i){
        this.i = i;
    }
}

public class FinalData {
    private static Random rand = new Random(47);
    private String id;
    public FinalData(String id){
        this.id = id;
    }
    private final int value_one = 9;
    private static final int VALUE_TWO = 99;
    public static final int VALUE_THREE = 39;
    private final int i4 = rand.nextInt(20);
    static final int INT_5 = rand.nextInt(20);
    private Value v1 = new Value(11);
    private final Value v2 = new Value(22);
    static final Value V3 = new Value(33);
    private final int[] a = {1,2,3,4,5,6};
    @Override
    public String toString(){
        return id+", i4="+i4+",INT_5 = "+INT_5;
    }
    public static void main(String[] args){
        FinalData fd1 = new FinalData("fd1");
        //fd1.value_one++; 錯誤,final修飾的基本類型數據的值不能改變
        fd1.v2.i++;
        fd1.v1 = new Value(9); //可以操作,因為v1不是final數據
        //fd1.v2 = new Value(0);  錯誤,final修飾的引用類型數據的內存地址不能改變
        //fd1.v3 = new Value(5);  錯誤,final修飾的引用類型數據的內存地址不能改變
        //fd1.a = new int[3];  /錯誤,final修飾的引用類型數據的內存地址不能改變
        System.out.println(fd1);   // fd1, i4=15,INT_5 = 18
        System.out.println("creating new FinalData");
        FinalData fd2 = new FinalData("fd2");  
        System.out.println(fd1);     //fd1, i4=15,INT_5 = 18
        System.out.println(fd2);    //fd2, i4=13,INT_5 = 18
    }
}

    上面例子驗證了final修飾的基本數據類型和引用數據類型的區別。根據i4和INT_5的輸出值可以得出結論,在編譯期我們不能因為數據是final 的就可以知道它的值,只有在運行時才會確定它的值。同時這裏也展示了靜態和非靜態的區別,帶有static關鍵字的數據在裝載時被初始化,非靜態的數據是在創建對象時間初識化的。例如:

package cn.wangze.test;

class useDemo{
    private int i;
    public useDemo(int ii){
        i = ii;
    }
}

public class BlankFinal {
    private final int i = 9;
    private final int j;
    private final useDemo ud;
    public BlankFinal(){
        j = 1;
        ud = new useDemo(10);
    }
    public BlankFinal(int x){
        j = 2;
        ud = new useDemo(x);
    }
    public static void main(String[] args){
        new BlankFinal();
        new BlankFinal(55);
    }
}

  上面例子我們在定義final變量是沒有給其賦值,這並沒有錯,但是一定要在構造器中給其賦值,不然編譯都不會通過。

  2、fianl參數

    當我們把方法傳入的形參定義為fianl時候,代表我們並不想在方法內部改變此參數的引用。

    public void change( final useDemo u2){
        u2.i = 20;
        //u2 = new useDemo(20); 報錯
    } 

    事實是當我們不帶有final關鍵字時,函數內部的引用改變也不會對外界的實參產生影響,所以我認為這裏final的作用是編譯期的阻攔,起到一個警示的作用。

  3、fianl方法

    一般我們使用final方法的目的就是防止子類對該類方法的覆蓋或修改。

    類中的所有private方法都隱式的制定為final的。因為private方法只會在本類顯示,即使是子類也不能操作該方法。有時候我們在子類中聲明與父類private方法相同名稱的方法,這樣並不會報錯,實際上我們並沒有覆蓋或者修改父類的private 方法,它只是一個和父類private方法具有相同名稱的新方法。

  4、fianl類

    一般我們使用final類的目的就是說明我們不打算用任何類繼承該類,即不希望該類有子類。

    帶有final關鍵字的類,其內部所有方法和數據都是隱式帶有final關鍵字的,因為沒有類可以繼承該類,代表著任何外界因素可以改變它的數據。

  總結:

    在我們設計程序的時候,會根據業務需求來決定是否對數據或方法或類帶有static和final關鍵字,這很重要,從另一個角度來說,final和static關鍵字的合理應用確實可以提高程序的效率,減少內存的消耗,當我們了解了類的初始化和加載過程,可能會對final和static有一個更加直觀的認識。

Java的static和final關鍵字的用法