參考鏈接: Java中的靜態塊static block
目錄直通車?
一、 類的加載特性與時機?
1、 類加載的特性?
2、 類加載的時機?
二、 static的三個常用?
1、 修飾成員變量?
2、 修飾成員方法?
3、 靜態塊(static{})?
?
一、 類的加載特性與時機?
在進入static之前,先補一下關于類的腦。?
1、 類加載的特性?
在JVM的生命周期里,每個類只會被加載一次。?
類加載的原則:延遲加載,能少加載就少加載,因為虛擬機的空間是有限的。?
2、 類加載的時機?
1)第一次創建對象要加載類.?
2)調用靜態方法時要加載類,訪問靜態屬性時會加載類。?
3)加載子類時必定會先加載父類。?
4)創建對象引用不加載類.?
5) 子類調用父類的靜態方法時?
? ? (1)當子類沒有覆蓋父類的靜態方法時,只加載父類,不加載子類?
? ? (2)當子類有覆蓋父類的靜態方法時,既加載父類,又加載子類?
6)訪問靜態常量,如果編譯器可以計算出常量的值,則不會加載類,例如:public static final int a =123;否則會加載類,例如:public static final int a = math.PI。?
二、 static的三個常用?
1、 修飾成員變量?
2、 修飾成員方法?
同C++是一樣的概念。但是在JVM里面,JVM也會劃分一個暫稱靜態存儲區,用于存放方法的定義。實際上從更大的角度而言,它存放的是各種類的定義,當我們通過new來生成對象時,會根據這里定義的類的定義去創建對象。?
下面觀察兩段代碼的輸出結果,加了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);
? ? }
?
? ? /**輸出結果
? ? ?* Name:zhangsan, Age:10
? ? ?* Name:lisi, Age:12
? ? ?*/
}?
public class Person {
? ? String name;
? ? // 給age加上static
? ? static int age;
? ? /* 其余代碼不變... */
?
? ? /**輸出結果
? ? ?* Name:zhangsan, Age:12
? ? ?* Name:lisi, Age:12
? ? ?*/
}?
結論:通過運行結果,可以看到 age都為12,只保存了最后一次給age賦的值。這是為什么呢,在內存里面發生了什么??
?
給age屬性加了static關鍵字之后,Person對象就不再擁有age屬性了,age屬性會統一交給Person類去管理,即多個Person對象只會對應一個age屬性,一個對象如果對age屬性做了改變,其他的對象都會受到影響。?
3、 靜態塊(static{})?
(1) static關鍵字還有一個比較關鍵的作用,用來形成靜態代碼塊(static{}(即static塊))以優化程序性能。?
(2) static塊可以置于類中的任何地方,類中可以有多個static塊。?
(3) 在類初次被加載的時候執行且僅會被執行一次(這是優化性能的原因!!!),會按照static塊的順序來執行每個static塊,一般用來初始化靜態變量和調用靜態方法。?
下面通過兩段代碼,說明 static{} 為什么能優化程序性能。?
實例?
/**
?* 每次調用isBornBoomer的時候
?* 都會生成startDate和birthDate兩個對象,造成了空間浪費
?*/
class Person{
? ? private Date birthDate;
? ? ?
? ? public Person(Date birthDate) {
? ? ? ? this.birthDate = birthDate;
? ? }
? ? ?
? ? boolean isBornBoomer() {
? ? ? ? Date startDate = Date.valueOf("1997");
? ? ? ? Date endDate = Date.valueOf("2019");
? ? ? ? return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
? ? }
}?
??
/**
?* 這里使用了static塊
?* 只需要進行一次的初始化操作
?* 節省內存空間,優化性能
?*/
class Person{
? ? private Date birthDate;
? ? private static Date startDate,endDate;
?
? ? static{
? ? ? ? startDate = Date.valueOf("1997");
? ? ? ? endDate = Date.valueOf("2019");
? ? }
? ? ?
? ? public Person(Date birthDate) {
? ? ? ? this.birthDate = birthDate;
? ? }
? ? ?
? ? boolean isBornBoomer() {
? ? ? ? return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
? ? }
}?
注意:強調一下static塊是會按照順序執行,與main入口函數無關。?
static還有一個不常用的用途,叫做 static靜態導包 。有興趣的朋友可以去了解一下。