關於Java關鍵字static與final一些總結
前幾天去面試,突然被問到Java關鍵字中的static和final,有點懵逼,有些概念性的東西竟然忘了,痛定思痛,故打算這樣一篇部落格來複習一下。
一、static
靜態修飾符,可作用在變數、方法,方法塊,類(內部類),所對應的呼叫時機和呼叫次數有所不同,主要分為以下幾種情況:
1、作用在變數和方法塊
public class ClassE { static int a = 1; static{ System.out.println("ClassE靜態程式碼塊"); } public ClassE() { System.out.println("ClassE構造"); } public static void main(String[] args) { ClassE classE = new ClassE(); ClassE classE2 = new ClassE(); } }
執行結果:
ClassE靜態方法塊
ClassE構造
ClassE構造
初始化一個類時,首先按程式碼順序,初始化類中的靜態變數和執行類中的靜態程式碼塊,然後在呼叫構造方法。但是應該注意的是,靜態變數的初始化和靜態程式碼塊的執行,只會在第一次呼叫該類時執行僅有的一次!!
此外,如果呼叫類中的靜態方法,也會先執行該類中所有靜態變數的初始化和靜態程式碼塊後,再呼叫該靜態方法,也是隻會在第一次呼叫該類時執行僅有的一次(不管呼叫該類中任意一靜態方法,都只會在第一次呼叫時執行且只會執行一次),例如:
public class ClassE { static int a = 1; static{ System.out.println("ClassE靜態方法塊"); } public ClassE() { System.out.println("ClassE構造"); } static void fun1(){ System.out.println("呼叫靜態方法1"); } static void fun2(){ System.out.println("呼叫靜態方法2"); } public static void main(String[] args) { ClassE.fun1(); ClassE.fun2(); } }
執行結果:
ClassE靜態方法塊
呼叫靜態方法1
呼叫靜態方法2
注意:不管靜態還是非靜態的變數都可以被子類繼承和覆蓋(即父類中定義一個靜態變數,可以通過子類進行呼叫)。
public class ClassB {
static int a = 1;
}
public class ClassA extends ClassB {
public static void main(String[] args) {
int z = ClassA.a;//合法操作
}
}
如果在子類中重寫該靜態變數,父類中該靜態變數就會被隱藏。
2、作用在方法
靜態方法,只要定義了類,不必建立類的例項就可使用。
public class ClassE { public ClassE() { } static void fun1(){ System.out.println("呼叫靜態方法1"); } void fun2(){ System.out.println("呼叫非靜態方法2"); } public static void main(String[] args) { ClassE.fun1(); ClassE classE = new ClassE(); classE.fun2(); } }
靜態方法的繼承與靜態變數的繼承一致,可參照靜態變數的做法進行操作。注意,靜態方法中無法使用super關鍵字,所有有關於super關鍵字的一切操作都無實現。
3、靜態內部類
關鍵字static不能修飾外部類,只能修飾內部類。
public class ClassD {
static class ClassE{
public ClassE() {
System.out.println("靜態類構造方法");
}
void fun(){
System.out.println("靜態類構造方法");
}
}
public static void main(String[] args) {
ClassE classE = new ClassE();classE.fun();
}
}
靜態內部類的作用:為了降低包的深度,方便類的使用,靜態內部類適用於包含類當中,但又不依賴與外在的類,只是為了方便管理類結構而定義。在建立靜態內部類的時候,不需要外部類物件的引用。
靜態內部類和非靜態內部類區別:非靜態內部類可以呼叫外部類變數,靜態內部類不可以呼叫外部類非靜態變數。
4、靜態關鍵字Static對類初始化時呼叫程式碼順序的影響
子Class繼承含有static關鍵字父Class,構造子Class物件時,程式碼的執行順序:
//父類 public class ClassI { static int a = 1;//靜態變數 int b = 1;//全域性變數 static{ System.out.println("父類的靜態程式碼塊"); } public ClassI() { System.out.println("父類的構造方法"); } } //子類 public class ClassH extends ClassI{ static int c = 1; int d = 1;//全域性變數 static{ System.out.println("子類的靜態程式碼塊"); } public ClassH() { System.out.println("子類的構造方法"); } public static void main(String[] args) { ClassH classH = new ClassH(); } }
父類的靜態物件->子類的靜態物件->父類全域性變數宣告和初始化->父類的建構函式->子類全域性變數宣告和初始化->子類的建構函式
二、Final
該關鍵字用於表明不可修改或者不可繼承。可以作用於變數,方法,類
1、作用在類上面說明該類不可被繼承
2、作用在方法上,說明在繼承該類的子類不可修改該方法。
3、作用在變數上,說明該變數不可變(注意:在定義final型別的變數時,需要初始化該值,否則會報錯)
關鍵字final對程式碼的呼叫順序沒有影響,用法也比關鍵字static簡單。