【java】class(類) 的access specifier (訪問權限規定),以及static和final關鍵字

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

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章