final,static,this,super 關鍵字總結

final,static,this,super 關鍵字總結

final 關鍵字

final關鍵字主要用在三個地方:變量、方法、類。函數

  1. 對於一個final變量,若是是基本數據類型的變量,則其數值一旦在初始化以後便不能更改;若是是引用類型的變量,則在對其初始化以後便不能再讓其指向另外一個對象。
  2. 當用final修飾一個類時,代表這個類不能被繼承。final類中的全部成員方法都會被隱式地指定爲final方法。
  3. 使用final方法的緣由有兩個。第一個緣由是把方法鎖定,以防任何繼承類修改它的含義;第二個緣由是效率。在早期的Java實現版本中,會將final方法轉爲內嵌調用。可是若是方法過於龐大,可能看不到內嵌調用帶來的任何性能提高(如今的Java版本已經不須要使用final方法進行這些優化了)。類中全部的private方法都隱式地指定爲final。

static 關鍵字

static 關鍵字主要有如下四種使用場景:性能

  1. 修飾成員變量和成員方法: 被 static 修飾的成員屬於類,不屬於單個這個類的某個對象,被類中全部對象共享,能夠而且建議經過類名調用。被static 聲明的成員變量屬於靜態成員變量,靜態變量 存放在 Java 內存區域的方法區。調用格式:類名.靜態變量名 類名.靜態方法名()
  2. 靜態代碼塊: 靜態代碼塊定義在類中方法外, 靜態代碼塊在非靜態代碼塊以前執行(靜態代碼塊—>非靜態代碼塊—>構造方法)。 該類無論建立多少對象,靜態代碼塊只執行一次.
  3. 靜態內部類(static修飾類的話只能修飾內部類): 靜態內部類與非靜態內部類之間存在一個最大的區別: 非靜態內部類在編譯完成以後會隱含地保存着一個引用,該引用是指向建立它的外圍類,可是靜態內部類卻沒有。沒有這個引用就意味着:1. 它的建立是不須要依賴外圍類的建立。2. 它不能使用任何外圍類的非static成員變量和方法。
  4. 靜態導包(用來導入類中的靜態資源,1.5以後的新特性): 格式爲:import static 這兩個關鍵字連用能夠指定導入某個類中的指定靜態資源,而且不須要使用類名調用類中靜態成員,能夠直接使用類中靜態成員變量和成員方法。

this 關鍵字

this關鍵字用於引用類的當前實例。 例如:測試

class Manager {
    Employees[] employees;
     
    void manageEmployees() {
        int totalEmp = this.employees.length;
        System.out.println("Total employees: " + totalEmp);
        this.report();
    }
     
    void report() { }
}

在上面的示例中,this關鍵字用於兩個地方:優化

  • this.employees.length:訪問類Manager的當前實例的變量。
  • this.report():調用類Manager的當前實例的方法。

此關鍵字是可選的,這意味着若是上面的示例在不使用此關鍵字的狀況下表現相同。 可是,使用此關鍵字可能會使代碼更易讀或易懂。this

super 關鍵字

super關鍵字用於從子類訪問父類的變量和方法。 例如:spa

public class Super {
    protected int number;
     
    protected showNumber() {
        System.out.println("number = " + number);
    }
}
 
public class Sub extends Super {
    void bar() {
        super.number = 10;
        super.showNumber();
    }
}

在上面的例子中,Sub 類訪問父類成員變量 number 並調用其其父類 Super 的 showNumber() 方法。

使用 this 和 super 要注意的問題:

  • 在構造器中使用 super() 調用父類中的其餘構造方法時,該語句必須處於構造器的首行,不然編譯器會報錯。另外,this 調用本類中的其餘構造方法時,也要放在首行。
  • this、super不能用在static方法中。

簡單解釋一下:

被 static 修飾的成員屬於類,不屬於單個這個類的某個對象,被類中全部對象共享。而 this 表明對本類對象的引用,指向本類對象;而 super 表明對父類對象的引用,指向父類對象;因此, this和super是屬於對象範疇的東西,而靜態方法是屬於類範疇的東西

參考

static 關鍵字詳解

static 關鍵字主要有如下四種使用場景

  1. 修飾成員變量和成員方法
  2. 靜態代碼塊
  3. 修飾類(只能修飾內部類)
  4. 靜態導包(用來導入類中的靜態資源,1.5以後的新特性)

修飾成員變量和成員方法(經常使用)

被 static 修飾的成員屬於類,不屬於單個這個類的某個對象,被類中全部對象共享,能夠而且建議經過類名調用。被static 聲明的成員變量屬於靜態成員變量,靜態變量 存放在 Java 內存區域的方法區。

方法區與 Java 堆同樣,是各個線程共享的內存區域,它用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。雖然Java虛擬機規範把方法區描述爲堆的一個邏輯部分,可是它卻有一個別名叫作 Non-Heap(非堆),目的應該是與 Java 堆區分開來。

HotSpot 虛擬機中方法區也常被稱爲 「永久代」,本質上二者並不等價。僅僅是由於 HotSpot 虛擬機設計團隊用永久代來實現方法區而已,這樣 HotSpot 虛擬機的垃圾收集器就能夠像管理 Java 堆同樣管理這部份內存了。可是這並非一個好主意,由於這樣更容易遇到內存溢出問題。

調用格式:

  • 類名.靜態變量名
  • 類名.靜態方法名()

若是變量或者方法被 private 則表明該屬性或者該方法只能在類的內部被訪問而不能在類的外部被訪問。

測試方法:

public class StaticBean {

    String name;
    靜態變量
    static int age;

    public StaticBean(String name) {
        this.name = name;
    }
    靜態方法
    static void SayHello() {
        System.out.println(Hello i am java);
    }
    @Override
    public String toString() {
        return StaticBean{ +
                name=' + name + ''' + age + age +
                '}';
    }
}
public class StaticDemo {

    public static void main(String[] args) {
        StaticBean staticBean = new StaticBean(1);
        StaticBean staticBean2 = new StaticBean(2);
        StaticBean staticBean3 = new StaticBean(3);
        StaticBean staticBean4 = new StaticBean(4);
        StaticBean.age = 33;
        StaticBean{name='1'age33} StaticBean{name='2'age33} StaticBean{name='3'age33} StaticBean{name='4'age33}
        System.out.println(staticBean+ +staticBean2+ +staticBean3+ +staticBean4);
        StaticBean.SayHello();Hello i am java
    }

}

靜態代碼塊

靜態代碼塊定義在類中方法外, 靜態代碼塊在非靜態代碼塊以前執行(靜態代碼塊—非靜態代碼塊—構造方法)。 該類無論建立多少對象,靜態代碼塊只執行一次.

靜態代碼塊的格式是

static {    
語句體;   
}

一個類中的靜態代碼塊能夠有多個,位置能夠隨便放,它不在任何的方法體內,JVM加載類時會執行這些靜態的代碼塊,若是靜態代碼塊有多個,JVM將按照它們在類中出現的前後順序依次執行它們,每一個代碼塊只會被執行一次。

靜態代碼塊對於定義在它以後的靜態變量,能夠賦值,可是不能訪問.

靜態內部類

靜態內部類與非靜態內部類之間存在一個最大的區別,咱們知道非靜態內部類在編譯完成以後會隱含地保存着一個引用,該引用是指向建立它的外圍類,可是靜態內部類卻沒有。沒有這個引用就意味着:

  1. 它的建立是不須要依賴外圍類的建立。
  2. 它不能使用任何外圍類的非static成員變量和方法。

Example(靜態內部類實現單例模式)

public class Singleton {
    
    聲明爲 private 避免調用默認構造方法建立對象
    private Singleton() {
    }
    
    聲明爲 private 代表靜態內部該類只能在該 Singleton 類中被訪問
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getUniqueInstance() {
        return SingletonHolder.INSTANCE;
    }
}

當 Singleton 類加載時,靜態內部類 SingletonHolder 沒有被加載進內存。只有當調用 getUniqueInstance() 方法從而觸發 SingletonHolder.INSTANCE 時 SingletonHolder 纔會被加載,此時初始化 INSTANCE 實例,而且 JVM 能確保 INSTANCE 只被實例化一次。

這種方式不只具備延遲初始化的好處,並且由 JVM 提供了對線程安全的支持。

靜態導包

格式爲:import static

這兩個關鍵字連用能夠指定導入某個類中的指定靜態資源,而且不須要使用類名調用類中靜態成員,能夠直接使用類中靜態成員變量和成員方法

Math. --- 將Math中的全部靜態資源導入,這時候能夠直接使用裏面的靜態方法,而不用經過類名進行調用
  若是隻想導入單一某個靜態方法,只須要將換成對應的方法名便可
 
import static java.lang.Math.;

  換成import static java.lang.Math.max;具備同樣的效果
 
public class Demo {
  public static void main(String[] args) {
 
    int max = max(1,2);
    System.out.println(max);
  }
}

補充內容

靜態方法與非靜態方法

靜態方法屬於類自己,非靜態方法屬於從該類生成的每一個對象。 若是您的方法執行的操做不依賴於其類的各個變量和方法,請將其設置爲靜態(這將使程序的佔用空間更小)。 不然,它應該是非靜態的。

Example

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

    public static String method1() {
       return An example string that doesn't depend on i (an instance variable);
       
    }

    public int method2() {
       return this.i + 1;  Depends on i
    }

}

你能夠像這樣調用靜態方法:Foo.method1()。 若是您嘗試使用這種方法調用 method2 將失敗。 但這樣可行:Foo bar = new Foo(1);bar.method2();

總結:

  • 在外部調用靜態方法時,可使用」類名.方法名」的方式,也可使用」對象名.方法名」的方式。而實例方法只有後面這種方式。也就是說,調用靜態方法能夠無需建立對象。
  • 靜態方法在訪問本類的成員時,只容許訪問靜態成員(即靜態成員變量和靜態方法),而不容許訪問實例成員變量和實例方法;實例方法則無此限制

static{}靜態代碼塊與{}非靜態代碼塊(構造代碼塊)

相同點: 都是在JVM加載類時且在構造方法執行以前執行,在類中均可以定義多個,定義多個時按定義的順序執行,通常在代碼塊中對一些static變量進行賦值。

不一樣點: 靜態代碼塊在非靜態代碼塊以前執行(靜態代碼塊—非靜態代碼塊—構造方法)。靜態代碼塊只在第一次new執行一次,以後再也不執行,而非靜態代碼塊在每new一次就執行一次。 非靜態代碼塊可在普通方法中定義(不過做用不大);而靜態代碼塊不行。

通常狀況下,若是有些代碼好比一些項目最經常使用的變量或對象必須在項目啓動的時候就執行的時候,須要使用靜態代碼塊,這種代碼是主動執行的。若是咱們想要設計不須要建立對象就能夠調用類中的方法,例如:Arrays類,Character類,String類等,就須要使用靜態方法, 二者的區別是 靜態代碼塊是自動執行的而靜態方法是被調用的時候才執行的.

Example

public class Test {
    public Test() {
        System.out.print(默認構造方法!--);
    }

     非靜態代碼塊
    {
        System.out.print(非靜態代碼塊!--);
    }
     靜態代碼塊
    static {
        System.out.print(靜態代碼塊!--);
    }

    public static void test() {
        System.out.print(靜態方法中的內容! --);
        {
            System.out.print(靜態方法中的代碼塊!--);
        }

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

        Test test = new Test();   
        Test.test();靜態代碼塊!--靜態方法中的內容! --靜態方法中的代碼塊!--
    }

當執行 Test.test(); 時輸出:

靜態代碼塊!--靜態方法中的內容! --靜態方法中的代碼塊!--

當執行 Test test = new Test(); 時輸出:

靜態代碼塊!--非靜態代碼塊!--默認構造方法!--

非靜態代碼塊與構造函數的區別是: 非靜態代碼塊是給全部對象進行統一初始化,而構造函數是給對應的對象初始化,由於構造函數是能夠多個的,運行哪一個構造函數就會創建什麼樣的對象,但不管創建哪一個對象,都會先執行相同的構造代碼塊。也就是說,構造代碼塊中定義的是不一樣對象共性的初始化內容。

參考

  • httpsblog.csdn.netchen13579867831articledetails78995480
  • httpwww.cnblogs.comchenssyp3388487.html
  • httpwww.cnblogs.comQian123p5713440.html
相關文章
相關標籤/搜索