第九天(上) final和static關鍵字
這個時候就需要一個關鍵字final 意為 最終的 不可變的
Final是一個比較強的修飾符,可以用來修飾類,類的成員,以及方法
Final修飾類
在類的前面加上final
Final類不可以被繼承,但可以繼承其他類,是個太監.其成員方法也默認為final的,但成員變量是可以改變的
在使用final修飾類的時候,要註意謹慎選擇,除非這個類真的在以後不會用來繼承或者出於安全的考慮,盡量不要將類設計為final類。
Final修飾方法
l 子類可以繼承final修飾的方法,但不能重寫.
l 父類中沒有被final修飾的方法,子類繼承後可以用final修飾
l 如果父類中final修飾的方法同時訪問控制權限為private,將會導致子類中不能直接繼承到此方法,因此,此時可以在子類中定義相同的方法名和參數,此時不再產生重寫與final的矛盾,而是在子類中重新定義了新的方法。
註:類的private方法會隱式地被指定為final方法。
Final修飾局部變量:
修飾基本數據類型
Final修飾的變量稱為常量,只能賦值一次,就不會被改變即使賦的新值與舊值一樣也不可以。
修飾引用數據類型
引用數據類型的值是地址值,被final修飾後不可以改變地址值
Final修飾成員變量
修飾成員變量時,成員變量需要在創建對象前復制
1直接賦值 通過等號
2構造方法中賦值 沒有顯式的賦值那麽多個構造方法都要為其賦值
Final修飾成員變量時,固定的不是內存中的值,而是手動的賦值(成員變量是有默認值的)
Final修飾方法參數
有點懵比,查了好多沒有找到一個令人信服的,說法也不一樣
關於final的一些題
public class Test {
public static void main(String[] args) {
String a = "hello2";
final String b = "hello";
String d = "hello";
String c = b + 2;
String e = d + 2;
System.out.println((a == c));
System.out.println((a == e));
System.out.println(a.equals(e));
}
}
結果true
false
True
為什麽呢?
b被聲明成了final的了,所以就是常量,常量表達式String c = b + 2;,JVM會優化成String c = "hello" + 2;,這個結果是變成編譯期就是已知了,指向常量池中的hello2字符串,也就是a。
public class Test {
public static void main(String[] args) {
String a = "hello2";
final String b = getHello();
String c = b + 2;
System.out.println((a == c));
}
public static String getHello() {
return "hello";
}
}
結果:
false
這裏的b雖然是常量,但是在編譯期是不能獲得值的,只有在運行的時候才會調用函數,初始化賦值,所以這時的String c = b+2是運行期間計算出來的,而加號連接運算符,內部則是調用的StringBuilder,然後toString,所以c相當於是new出來的String,即c是指向堆內存的地址,c內部的char數組才指向常量池中的字符串,所以明顯a != c.
希望看了深入理解jvm虛擬機後可以更好的理解這些問題.
Static
定義類的時候,類中會有相應的方法和屬性,而方法和屬性都是通過創建本類對象調用的,當調用對象的某個方法時,這個方法又沒有訪問特定的數據,創建這個對戲那個就有點多余,或者說沒有對象都有一模一樣的常量,每new一個就出現一次這個常量,又沒有辦法一勞永逸呢
要解決上面的問題就要用到關鍵字static.
代表全局,靜態的意思,用來修飾成員變量,成員方法,以及代碼塊.其次還有靜態內部類以後有機會了解.
Static的作用: 簡單來說就是方便在沒有創建對象的情況下來調用方法或者變量.
Java中並不存在全局變量的概念,但我們可以用static來實現一個偽全局變量的概念,
Static修飾變量:被static修飾(只能修飾成員變量)變量稱為靜態變量,沒有使用static修飾的叫實例變量.伴隨著類的加載完成初始化.分配一次內存.每一個對象對靜態變量的操作都會反應到其他對象上。
什麽時候該使用static修飾呢?
當這個成員會被類的所有對象所共享,一般我們把共性的數據定義為靜態變量
有什麽好處呢
對象之間共享數據,訪問方便,節約內存
怎麽調用呢
類名.靜態成員變量名
對象名.靜態成員變量名 ------不建議使用該方式,會出現警告
Static修飾方法:被static修飾的方法稱為靜態方法.
他在類加載的時候就存在了,它不依賴於任何實例,所以static方法必須實現,也就是說他不能是抽象方法abstract。
什麽時候該使用static修飾
成員方法跟著變量走,靜態方法只能訪問靜態變量,如果成員方法中引用了靜態的其他成員,那麽這個方法就要聲明為靜態的方法.
怎麽調用
類名.靜態成員方法名(參數)
對象名.靜態成員方法名(參數) ------不建議使用該方式,會出現警告
註意事項:
靜態方法不能操作非靜態變量,也不能調用非靜態方法。(這個可以這樣理解:靜態方法屬於類,直接通過類名就可以調用,而此時可能沒有任何實例,更談不上操作實例變量和調用實例方法了。)
同理,靜態也不能使用this和super關鍵字.
所以main方法中不能直接調用非靜態的方法.
為什麽mian方法時靜態的
為了使在調用mian方法前不創建任何實例對象.
Static靜態代碼塊
被static修飾的代碼塊,我們稱之為靜態代碼塊,靜態代碼塊會隨著類的加載一塊執行,而且他可以隨意放,可以存在於該了的任何地方。
用來初始化靜態變量。
在類加載時,在執行main方法之前執行相關操作。
沒有main方法的程序可以執行嗎?
Jdk1.7之前可以
之後會報錯
靜態導包
感覺沒什麽用jdk1.5之後
其目的是為了減少字符輸入量,提高代碼的可閱讀性,以便更好地理解程序。
采用static導入包後,在不與當前類的方法名沖突的情況下,無需使用“類名.方法名”的方法去調用類方法了,直接可以采用"方法名"去調用類方法,就好像是該類自己的方法一樣使用即可。
建議對於靜態導入,一定要遵循兩個規則:
1.不要使用*(星號)通配符,除非是導入靜態常量(只包含常量的類或接口)。
2. 方法名是具有明確、清晰表象意義的工具類。
靜態內部類
內部類了解
第九天(上) final和static關鍵字