Java訪問權限控制
修飾符用來定義類、方法或者變量,通常放在語句的最前端。
Java語言提供了很多修飾符,主要分為以下兩類:
- 訪問修飾符
- 非訪問修飾符
其中非訪問修飾符主要有:static、final、abstract、synchronized和volatile,非訪問修飾符根據各自的特性來保證特定功能的實現。
Java中使用訪問控制符來保護對類、變量、方法和構造方法的訪問,訪問控制修飾符對應的權限控制的大小情況為:public > protected > default(包訪問權限) > private。
1. 編譯單元和包
編譯單元:即為最小的可以被編譯且執行的Java文件。
一個.java文件就是一個編譯單元,一個編譯單元必須只包含有一個public類,可以包含有其他非public的類,並且用publi類標示的類名必須和文件名相同。如果.java文件中不包含有publi類,則這個類也是沒有意義的,因為不能被外界所訪問。.java文件中包含有幾個類,編譯后就會生成幾個.class文件。
包含有一組類,是以一個名字空間集合在一起的類而已。
2. 訪問控制修飾符
-
public : 對所有類可見
使用對象:類、接口、變量、方法
-
protected : 對同一包內的類和所有子類可見
使用對象:變量、方法。 注意:不能修飾類(外部類)
-
default (即缺省,什么也不寫): 在同一包內可見,不使用任何修飾符
使用對象:類、接口、變量、方法。
-
private : 在本類中可見
使用對象:變量、方法。 注意:不能修飾類(外部類)
private和protected修飾符不能用以修飾類/接口
2.1 公有訪問修飾符-public
被聲明為 public 的類、方法、構造方法和接口能夠被任何其他類訪問。
如果幾個相互訪問的 public 類分布在不同的包中,則需要導入相應 public 類所在的包。
由於類的繼承性,類所有的公有方法和變量都能被其子類繼承。
2.2 受保護的訪問修飾符-protected
protected 又稱繼承訪問權限
protected 需要從以下兩個點來分析:
-
子類與基類在同一包中:被聲明為 protected 的變量、方法和構造器能被同一個包中的任何其他類訪問;
-
子類與基類不在同一包中:在子類中,子類實例可以訪問其從基類繼承而來的 protected 方法,而不能訪問基類實例的protected方法
子類能訪問 protected 修飾符聲明的方法和變量,這樣就能避免不相關的類使用這些方法和變量。
在碰到涉及protected成員的調用時,首先要確定出該protected成員來自何方,其可見性范圍是什么,然后就可以判斷出當前用法是否可行了
package p2;
class MyObject2 {
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
package p22;
public class Test2 extends MyObject2 {
public static void main(String args[]) {
MyObject2 obj = new MyObject2();
obj.clone(); // Compile Error ----(1)
Test2 tobj = new Test2();
tobj.clone(); // Complie OK ----(2)
}
}
對於(1)而言,clone()方法來自於類MyObject2本身,因此其可見性為包p2及MyObject2的子類,雖然Test2是MyObject2的子類,但在Test2中不能訪問基類MyObject2的protected方法clone(),因此編譯不通過;
對於(2)而言,由於在Test2中訪問的是其本身實例的從基類MyObject2繼承來的的clone(),因此編譯通過。
2.3 默認訪問修飾符-不使用任何關鍵字
使用默認訪問修飾符聲明的變量和方法,對同一個包內的類是可見的。
接口里的變量都隱式聲明為 public static final,而接口里的方法默認情況下訪問權限為 public。
2.4 私有訪問修飾符-private
被聲明為 private 的方法、變量和構造方法只能被所屬類訪問,並且類和接口不能聲明為 private。
聲明為私有訪問類型的變量可以通過類中公共(public修飾)的 getter 方法被外部類訪問。
private 訪問修飾符的使用主要用來隱藏類的實現細節和保護類的數據
3. 相關問題
3.1 訪問控制和繼承
注意以下方法繼承的規則:
-
父類中聲明為 public 的方法在子類中也必須為 public。
-
父類中聲明為 protected 的方法在子類中要么聲明為 protected,要么聲明為 public,不能聲明為 private。
-
父類中聲明為 private 的方法,不能夠被繼承。
3.2 構造器的訪問權限
構造器的訪問權限可以是以上四種權限中的任意一種:
-
采用 private:一般是不允許直接構造這個類的對象,再結合工廠方法(static方法),實現單例模式。注意:所有子類都不能繼承它。
-
采用包訪問控制:比較少用,這個類的對象只能在本包中使用,但是如果這個類有static 成員,那么這個類還是可以在外包使用;(也許可以用於該類的外包單例模式)。
注意:外包的類不能繼承這個類; -
采用 protected :就是為了能讓所有子類繼承這個類,但是外包的非子類不能訪問這個類;
-
采用 public :對於內外包的所有類都是可訪問的;
注意: 構造方法有點特殊,因為子類的構造器初始化時,都要調用父類的構造器,所以一旦父類構造器不能被訪問,那么子類的構造器調用失敗,意味子類繼承父類失敗!
參考鏈接: