java final與static關鍵字

final關鍵字

final關鍵字的基本用法

  • 修飾類
    final關鍵字修飾類,表明該類不能被繼承,如果一個類你想不讓它被繼承,可以將其用final關鍵字修飾,被final修飾後類中的方法被隱式的被指定爲final方法。

  • 修飾方法
    final關鍵字修飾方法,表明該方法不能被繼承類修改,被private修飾的方法隱式的被指定爲final方法

  • 修飾變量
    final關鍵字修飾變量,如果變量是基本數據類型,表明其數值一旦被初始化後就不能被改變;如果是引用數據類型,表明一旦被初始化後就不能指向另一個對象。

final關鍵字注意的問題

  • final變量與普通變量的區別
    final變量通常有三個地方可以賦值:直接賦值,構造函數中,初始化塊(如果一段代碼對所有對象都相同,並且無需接收參數,則可以將其移到初始化塊中)中
public class FinalTest {
    public static void main(String[] arg){
        String a = "Hello2";
        final String b = "Hello";
        //final String b;
        //b = "Hello";
        String c = "Hello";
        String d = b+2;
        String e = c+2;
        System.out.println(a==d);
        System.out.println(a==e);
        System.out.println(a.equals(d));
        System.out.println(a.hashCode());
        System.out.println(e.hashCode());
        System.out.println(d.hashCode());
        System.out.println(a.equals(d));
        System.out.println(a.equals(e));
    }
}
結果:true(flase)
false
true
-2137068096
-2137068096
-2137068096
true

第二個結果之所以爲false,是因爲final修飾的變量表示常量,在編譯期就能直接確定b的值,而c是變量,c的值在編譯期不能確定,只有在編譯期能確定相同的字符串才能指向常量池中同一個字符串。從這裏就能看出final變量與普通變量的區別:final修飾的變量如果賦值了在編譯期就能確定(沒賦值時和普通變量一樣,如上面結果爲flase),而普通變量不行。

  • final關鍵字修飾的變量內容是否可以改變
    如果修飾的變量是基本數據類型或String類型,一旦被初始化後就不能被修改,如果是引用類型的變量,一旦被初始化賦值後,不能再指向其他的對象,但是引用對象本身的變量還是可以改變。
public class FinalTest {
    public static void main(String[] arg){
        final Num num = new Num();
        System.out.println(++num.i);
    }
}
class Num{
    public int i= 0 ;
}
結果爲1

static關鍵字

  • static關鍵字:被static修飾的成員變量和成員方法獨立於該類的任何對象。也就是說,它不依賴類特定的實例,被類的所有實例共享。只要這個類被加載,Java虛擬機就能根據類名在運行時數據區的方法區內定找到他們(即通過類名訪問)。因此,static對象可以在它的任何對象創建之前訪問,無需引用任何對象。

  • static關鍵字的作用:方便在沒有創建對象時調用方法及變量

static關鍵字的基本用法

  • 修飾變量

    • static表示全局或者靜態的意思,static變量也稱爲靜態變量,可以不用實例化就直接訪問,static變量可以用private修飾,表示static變量可以在該類的靜態代碼塊中或被其他靜態(非靜態)方法訪問。其他類不能通過類名直接訪問。
    • static變量與普通變量的區別:static變量是被類中所用對象所共享,在內存中只保留一份副本,它當且僅當類被初次加載時初始化,普通變量是對象所擁有的,當對象被創建的時候初始化,在內存中可以有多個副本,各個副本之間互不影響。
  • 修飾方法

    • static修飾的方法爲靜態方法,靜態方法不依賴於任何對象的調用,靜態方法不能訪問該類中非靜態成員及方法,但能訪問靜態成員及方法;非靜態方法可以訪問類中靜態成員及方法。
  • 修飾代碼塊

    • static修飾代碼塊爲靜態代碼塊,主要是優化性能,static代碼塊在類加載的時候只會被加載一次,避免了資源的浪費。static代碼塊可以有很多,加載時依次加載。
  • static關鍵字不能修飾局部變量:(自己的理解)首先static修飾的變量是靜態變量,被所有的對象所共有,如果可以修飾局部變量,局部變量屬於方法內,不被對象所共享;其次局部變量是用到的時候加載,static變量是類加載時即加載,加載順序不符


Java中類的加載及執行順序:

  • 父類靜態變量–>父類靜態代碼塊–>子類靜態變量–>子類靜態代碼塊–>(main方法)–>父類非靜態變量–>父類非靜態代碼塊–>父類構造方法–>子類非靜態變量–>子類非靜態代碼塊–>子類構造方法
public class Dervied extends Base {

    private String name = "dervied";
    //private static String name1 = "dervide";
    public Dervied() {
        tellName();
        printName();
    }
    static{
    System.out.println("devied");
    }
    {
    System.out.println("devied2");
    }
    public void tellName() {
        System.out.println("Dervied tell name: " + name);
        //System.out.println("Dervied tell name: " + name1);
    }

    public void printName() {
        System.out.println("Dervied print name: " + name);
        //System.out.println("Dervied tell name: " + name1);
    }

    public static void main(String[] args){

        new Dervied();    
    }
}

class Base {

    private String name = "base";
    public Base() {
        tellName();
        printName();
    }
    static{
    System.out.println("base");
    }
    {
    System.out.println("base2");
    }
    public void tellName() {
        System.out.println("Base tell name: " + name);
    }

    public void printName() {
        System.out.println("Base print name: " + name);
    }
}
結果:base
devied
base2
Dervied tell name:null
Dervied tell name:null
//添加靜態變量時的結果
//Dervied tell name:devide
//Dervied tell name:devide
devied2
Dervied tell name:devide
Dervied tell name:devide

注:出現null的原因,子類繼承父類重寫父類的方法,由類的加載順序可知,先加載父類的構造函數,調用父類的方法,但是父類的方法被子類重寫,即調用子類重寫後的方法,但此時子類中的非靜態屬性還沒加載,即結果爲null。

另外:子類沒有顯示調用父類構造函數,不管子類構造函數是否帶參數都默認調用父類無參的構造函數,若父類沒有則編譯出錯。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章