修飾符final和static淺析

通常在進行分析的時候,會從三個方面進行分析:類、方法(構造方法、成員方法)、變量(成員變量(靜態變量、實例變量)、局部變量)。java

1、static修飾符:

被static修飾的變量和方法,被類的全部實例所共享。加載類時只分配一次內存。dom

  1. 靜態變量:能夠直接經過類名來訪問 Person.a;ide

  2. 靜態方法:能夠直接經過類名來訪問 Person.say();靜態方法內,能夠訪問靜態變量,可是不能使用this關鍵字不能訪問實例變量,由於被全部實例所共有,沒法判斷屬於哪一個實例對象函數

  3. 靜態代碼塊:java虛擬機在加載類時就執行代碼塊this

2、final修飾符:

有final修飾表示最終(不可再修改)的意思:指針

  1. final類:不能被繼承(即沒有子類);code

  2. final方法:不能被子類的方法覆蓋(final不用來修飾構造方法,父類與子類之間的構造方法不存在覆蓋關係,final修飾是沒有意義的);對象

  3. final修飾的變量:即常量,常量只能被賦值一次,以後不能改變。(如下靜態常量屬於編譯時常量(final static int a=2*3;在編譯的時就能計算出具體的值),在編譯的時候將這個值就放入到常量池中,a被訪問時類是不會被初始化的(這是類的被動使用)。訪問類的靜態變量或靜態方法的時候類會被初始化(這是類的主動使用)。但只有static修飾的常量,只會在類初始化的時候纔會賦值)。具體細節請參考「類的生命週期」---加載(堆區、方法區)--鏈接(驗證、準備(靜態變量分配內存、設置默認初始值爲0)、解析(符號引用替換爲直接引用,即指針指向方法區的內存位置))--初始化(程序對類或接口主動使用的時候纔會被初始化)。繼承

3、類的初始化時機:

類的初始化即java虛擬機爲類的static靜態變量賦予初始值(這和準備階段設置默認初始值爲0是不同的)。只有類的主動使用纔會初始化類接口

1.類的主動使用(6種):

1.1 建立類的實例:用new語句建立實例 Person ps=new Person();

1.2 調用類的靜態變量或對靜態變量賦值:

public class Person{
	
	//這和final static int a=2*3;是有區別的
	static int a=2*3;
	
	//Java在定義一個類的時候裏面只能放方法和屬性,這是規定死了的。
	//System.out.println()是在調用一個叫println的函數,
	//這裏是函數的調用而不是類裏面定義一個函數。因此須要用static代碼塊
	
	static{
		//static聲明的靜態代碼塊,
		//使得類在初始化的時候會被調用而不須要建立實例對象。
		//它這時候就不在任何一個方法中。
		System.out.println("init Person"); 
	}
}

        調用的時候寫:

//這樣就能夠在不new一個Person實例的狀況下,來初始化Person類了。
System.out.println("a="+Person.a);

1.3 調用類的靜態方法;

1.4 調用java API中的反射方法:Class.forName("Person");

1.5 初始化子類的時候會先初始化父類(但"父類"是接口的時候,不會先初始化它所實現的接口的,只有在程序在使用接口的靜態變量時纔會使靜態接口初始化)

1.6 java虛擬機啓動時被標明爲啓動類的類

2.類的被使用:

1.1 final類型的靜態變量在編譯的時候能計算出值(即編譯時常量,在編譯的時候將這個值就放入到常量池中了):
注: final類型的靜態變量在編譯的時候不能計算出變量的值的時候是會被初始化的

//變量a是編譯時常量
final static int a=2*3;  
//變量a不是是編譯時常量
final static int a=(int)Math.random();  

1.2 "父類"是接口的時候,不會先初始化它所實現的接口的,只有在程序在使用接口的靜態變量時纔會使靜態接口初始化

1.3 ClassLoader類的loadClass("Person")方法的時候,只是對類的加載,不是初始化。Class.forName("Person");纔會初始化

相關文章
相關標籤/搜索