眾所周知,static 是靜態修飾關鍵字:可以修飾變量,程序塊,方法,類。
1.修飾變量。
得知:如果static修飾的是變量,則JVM會將將其分配在內存堆上,該變量就與對象無關,所有對該變量的引用都指向同一個地址。
因此我們使用該變量的時候,直接指明類的靜態變量,當然修飾符必須 public
1 public class StaticBean {
2 public static String A = "A"; 3 }
使用方式
1 public static void main(String[] args) throws Exception{
2 System.out.println(StaticBean.A); 3 }
2.修飾程序塊,猜猜輸出結果是什么?。
1 public class BaseTest {
2
3 static{ 4 System.out.println("B"); 5 } 6 7 public static void main(String[] args) throws Exception{ 8 System.out.println("A"); 9 } 10 }
結論:JVM就會優先加載靜態塊中代碼,因此會優先輸出B,static 修飾代碼塊,這主要用於系統初始化。
B
A
3.修飾方法:在外部調用靜態方法時,可以使用"類名.方法名"的方式,也可以使用"對象名.方法名"的方式。而實例方法只有后面這種方式。也就是說,調用靜態方法可以無需創建對象,靜態方法在訪問本類的成員時,只允許訪問靜態成員,而不允許訪問實例成員變量和實例方法。
public class StaticBean {
public static String A = "A";
public String D;
public static void getMessage(){
System.out.println(A);
System.out.println(D);
}
}
上面代碼,哪句是錯誤的,很顯然。
System.out.println(D);
4.修飾類。在我們的熟知之中,static 修飾符一般用於修飾變量,程序塊,方法,但是什么時候使用static來修飾類呢?
內部類。如果在外部類聲明為static,程序會編譯都不會過。
內部類特點如下:
2.可以直接創建實例,不需要先創建外部類(普通內部類需要)
3.可以有靜態成員變量、方法(普通內部類不行)和非靜態成員變量、方法
4.只可以直接訪問外部類靜態成員,不可以直接訪問外部類的非靜態成員(普通內部類可以),需要通過傳入外部類引用的方式才能訪問
那就很簡單引出,什么時候會使用靜態內部類呢? 我們來看下以下一個例子
1 public class Outer {
2 private int i = 0; 3 4 public Outer() { 5 i++; 6 System.out.println("=====init Outer "+i+"===="); 7 8 } 9 10 public static Outer getInstance(){ 11 return Inner.INSTANCE; 12 } 13 //靜態內部類 14 public static class Inner{ 15 private static final Outer INSTANCE = new Outer(); 16 } 17 }
調用方
1 public class BaseTest {
2 public static void main(String[] args) throws Exception{ 3 for(int i = 0; i < 1000;i++) { 4 Outer.getInstance(); 5 } 6 } 7 }
輸出結果:
=====init Outer 1====
我們總結下:
由於 INSTANCE 是常量,因此只能賦值一次;它還是靜態的,因此隨着內部類一起加載,這種也是單例懶漢模式的一種實現方式,同時保證了線程安全。
final 關鍵字可以用來修飾類,方法和變量
1.修飾類
表示該類不允許被繼承,final類中的成員方法都會被隱式的指定為final方法。
public final class FinalBean {
public void test(){ } }
2.修飾方法
表示該方法不能被重寫,一個類的private方法會隱式的被指定為final方法。
以下例子SunFinalBean的test方法報錯。
public class FinalBean {
public final void test(){ } public class SunFinalBean extends FinalBean{ public void test(){ } } }
3.修飾變量
表示該變量必須初始化,且值不能改變。如果是基本類型則值不能改變,如果是引用類型,則引用地址不能改變,但是這個引用所指向的對象里面的內容還是可以改變的。
猜猜看,以下那句通不過編譯器編譯。
public class FinalBean {
private final int i = 0; private final int j; private final String name = ""; public FinalBean(){ j = 1; this.name.concat("123"); this.name = "123"; } }
這句,記住final的原理即可理解,那為什么this.name.concat("123");不會報錯呢,因為底層實現是返回一個新的String對象
this.name = "123";
那static final 一起用:
static修飾的屬性強調它們只有一個,final修飾的屬性表明是一個常數(創建后不能被修改)。static final修飾的屬性表示一旦給值,就不可修改,並且可以通過類名訪問。
static final也可以修飾方法,表示該方法不能重寫,可以在不new對象的情況下調用。
