1. access specifier (訪問權限規定)
There are four kinds.
1.1 public
對所有類都可用,包括在不同的package中
範圍:當前類 / 同一個package / 繼承類 / 其他package
1.2 protected
對繼承類,同一個packet中的類可用,對其他外部類都不可用(指不是同一個package)
範圍:當前類 / 同一個package / 繼承類
1.3 (default)
同一個package中的類可用,繼承類不可用,不是同一個package的類也不能用
範圍:當前類 / 同一個package
1.4 private
只對自己這個類可用,其他全都不可用(包括繼承類,同一個package中的類)
範圍:當前類
2. static關鍵字
static關鍵字是爲了方便在沒有創建對象的情況下來進行調用(方法/變量)
被static關鍵字修飾的方法或者變量不需要依賴於對象來進行訪問,只要類被加載了,就可以通過類名去進行訪問
static可以用來修飾類的成員方法、類的成員變量,另外可以編寫static代碼塊來優化程序性能
對於靜態方法來說,是沒有this的,因爲它不依附於任何對象,既然都沒有對象,就談不上this
在靜態方法中不能訪問非靜態成員方法和非靜態成員變量,但是在非靜態成員方法中是可以訪問靜態成員方法/變量的
main方法必須是static的,因爲程序在執行main方法的時候沒有創建任何對象,因此只有通過類名來訪問
1.1 static變量
static變量也稱作靜態變量,靜態變量和非靜態變量的區別是:靜態變量被所有的對象所共享,在內存中只有一個副本,它當且僅當在類初次加載時會被初始化。而非靜態變量是對象所擁有的,在創建對象的時候被初始化,存在多個副本,各個對象擁有的副本互不影響。
static成員變量的初始化順序按照定義的順序進行初始化。
1.2 static靜態代碼塊
static靜態代碼塊可以優化程序性能
在類初次被加載的時候,會按照static塊的順序來執行每個static塊,並且只會執行一次
優化前
優化後
所以只需要進行一次的初始化操作可以放在static代碼塊中進行
靜態代碼塊可以出現在類的任何地方(只要不是方法內部,記住,任何方法內部都不行),並且執行是按照static塊的順序執行的
Java中的static關鍵字不會影響到變量或者方法的作用域
雖然對於靜態方法來說沒有this,那麼在非靜態方法中能夠通過this訪問靜態成員變量嗎?
public class Main {
static int value = 33;
public static void main(String[] args) throws Exception{
new Main().printValue();
}
private void printValue(){
int value = 3;
System.out.println(this.value);
}
}
this代表什麼?this代表當前對象,那麼通過new Main()來調用printValue的話,當前對象就是通過new Main()生成的對象。而靜態變量是被對象所享有的,因此在printValue中的this.value的值毫無疑問是33。在printValue方法內部的value是局部變量,根本不可能與this關聯,所以輸出結果是33
靜態變量被所有的對象所共享,非靜態變量是對象所擁有的,在創建對象的時候被初始化
靜態成員變量雖然獨立於對象,但是不代表不可以通過對象去訪問,所有的靜態方法和靜態變量都可以通過對象訪問(只要訪問權限足夠)
static是不允許用來修飾局部變量。不要問爲什麼,這是Java語法的規定。
參考原文鏈接:http://www.cnblogs.com/dolphin0520/p/3799052.html
3. final關鍵字
final關鍵字可以用來修飾類、方法和變量(包括成員變量和局部變量)
當用final修飾一個類時,表明這個類不能被繼承
final類中的成員變量可以根據需要設爲final,但是要注意final類中的所有成員方法都會被隱式地指定爲final方法
用final修飾方法的原因有兩個。
第一個原因是把方法鎖定,以防任何繼承類修改它的含義;
第二個原因是效率。在早期的Java實現版本中,會將final方法轉爲內嵌調用。但是如果方法過於龐大,可能看不到內嵌調用帶來的任何性能提升。在最近的Java版本中,不需要使用final方法進行這些優化了。
類的private方法會隱式地被指定爲final方法
用final修飾變量
如果是基本數據類型的變量,則其數值一旦在初始化之後便不能更改;
如果是引用類型的變量,則在對其初始化之後便不能再讓其指向另一個對象。
深入研究
1. 當final變量是基本數據類型以及String類型時,如果在編譯期間能知道它的確切值,則編譯器會把它當做編譯期常量使用
但是要注意,只有在編譯期間能確切知道final變量值的情況下,編譯器纔會進行這樣的優化
2. 引用變量被final修飾之後,雖然不能再指向其他對象,但是它指向的對象的內容是可變的
public class Test {
public static void main(String[] args) {
MyClass myClass = new MyClass();
StringBuffer buffer = new StringBuffer("hello");
myClass.changeValue(buffer);
System.out.println(buffer.toString());
}
}
class MyClass {
void changeValue(final StringBuffer buffer) {
buffer.append("world");
}
}
用final進行修飾並沒有阻止在changeValue中改變buffer指向的對象的內容
如果把final去掉了,然後在changeValue中讓buffer指向了其他對象,也不會影響到main方法中的buffer,原因在於java採用的是值傳遞,對於引用變量,傳遞的是引用的值,也就是說讓實參和形參同時指向了同一個對象,因此讓形參重新指向另一個對象對實參並沒有任何影響。
參考原文:http://www.cnblogs.com/dolphin0520/p/3736238.html