成員變量的訪問權限
我看到很多地方談到關於Java里變量的訪問權限問題.
很多地方認為對於默認修飾符的理解是這樣的:
不寫時默認為friendly
但就我所知Java里沒有 friendly這一關鍵字.
當然學過C++的人都知道,在C++里有 friendly,而且其訪問權限和Java里不寫時默認情況一樣.
我覺的可以這樣理解,但不能這么認為.C++和Java畢竟是兩種不同的語言,許多規則是不同的.
如果我說的有哪里不正確,請大家改正,謝謝.
訪問權限修飾符聲明了成員變量的訪問權限。Java提供的顯示的訪問權限修飾符有3種,分別是:私有(private)、保護(protected)和公 共(public)。除此之外,還有一種默認的訪問權限:friendly,它並不是Java的關鍵字,只有當變量前面沒有寫明任何訪問權限修飾符時,就 默認以friendly作為訪問權限。為了表達上的方便,省略了其中"成員"兩字,將被這些修飾符所修飾的變量分別稱為私有變量、保護變量和公共變量。下 面分別討論各個修飾符的用法。
1.公共變量
凡是被public修飾的成員變量,都稱為公共變量,它可以被任何類所訪問。即允許該變量所屬的類中所有方法訪問,也允許其他類在外部訪問。
公共變量使用示例。
public class declarePublic{
public int publicVar=10; //定義一個公共變量
}
在類declarePublic中聲明了一個公共變量publicVar,它可以被任何類所訪問。下面這段程序中,類otherClass可以合法地修改變量publicVar的值,而無論otherClass位於什么地方。
public class otherClass{
void change(){
declarePublic ca=new declarePublic(); //創建一個declarePublic對象
ca.publicVar=20; //通過對象名來訪問它的公共變量,正確
}
}
用public修飾的變量,允許任何類在外部直接訪問,這破壞了封裝的原則,造成數據安全性能下降,所以除非有特別的需要,否則不要使用這種方案。
2.私有變量
凡是被private修飾的成員變量,都稱為私有變量。它只允許在本類的內部訪問,任何外部類都不能訪問它。
私有變量使用示例。
public class declarePrivate{
private int privateVar=10; //定義一個私有變量
void change(){
privateVar=20; //在本類中訪問私有變量,合法
}
}
如果企圖在類的外部訪問私有變量,編譯器將會報錯。
public class otherClass{
void change(){
declarePrivate ca=new declarePrivate(); //創建一個declarePrivate對象
ca.privateVar=20; //企圖訪問私有變量,非法
}
}
為了讓外部用戶能夠訪問某些私有變量,通常類的設計者會提供一些方法給外部調用,這些方法被稱為訪問接口。下面是一個改寫過的declarePrivate類。
public class declarePrivate{
private int privateVar=10; //定義一個私有變量
void change(){
privateVar=20;
}
public int getPrivateVar(){ //定義一個接口,返回私有變量privateVar的值
return privateVar;
}
public boolean setPrivateVar(int value){ //定義一個接口,可以設置privateVar
的值
//可以在這里先檢測value是否在允許的范圍內,然后再執行下面的語句。
privateVar = value;
return true;
}
}
私有變量很好地貫徹了封裝原則,所有的私有變量都只能通過程序員設計的接口來訪問,任何外部使用者都無法直接訪問它,所以具有很高的安全性。但是,在下面這兩種情況下,需要使用Java另外提供的兩種訪問類型:
通過接口訪問私有變量,將降低程序的性能,在程序性能比較重要的情況下,需要在安全性和效率間取得一個平衡。
私有變量無法被子類繼承,當子類必須繼承成員變量時,需要使用其他的訪問類型。
3.保護變量
凡是被protected修飾的變量,都被稱為保護變量。除了允許在本類的內部訪問之外,還允許它的子類以及同一個包中的其他類訪問。子類是指從該類派生出來的類。包是Java中用於管理類的一種松散的集合。二者的詳細情況將在第4章介紹。下面是一個簡單的例子。
保護變量使用示例。
下面這個程序先定義一個名為onlyDemo的包,declarProtected類就屬於這個包。
public class declareProtected{
protected int protectedVar=10; //定義一個保護變量
void change(){
protectedVar=20; //合法
}
}
說明:讀者編譯這個文件時,需要用這個命令(下同):
javac -d . 文件名
下面這個otherClass類也定義在onlyDemo包中,與declareProtected類同屬於一個包。
public class otherClass{ //它也在包onlyDemo中
void change(){
declareProtected ca=new declareProtected();
ca.protectedVar=20; //合法
}
}
下面這個deriveClass類是declareProtected的子類,它並不在onlyDemo包中。它也可以訪問保護變量protectedVar,但是只能通過繼承的方式訪問。
import onlyDemo.declareProtected; //引入需要的包
public class deriveClass extends declareProtected{ //定義一個子類
void change(){
//合法,改變的是deriveClass從declarProtected中所繼承的protectedVar值
protectedVar=30;
}
}
說明:import是Java中的關鍵字,用於引入某個包。這將在4.13節中詳細介紹。
子類如果不在父類的同一包中,是無法通過"對象名.變量名"的方式來訪問protected類型的成員變量,比如下面這種訪問是非法的:
import onlyDemo.declareProtected;
public class deriveClass extends declareProtected{ //定義一個子類
void change(){
declareProtected ca=new declareProtected();
ca.protectedVar=30; //錯誤,不允許訪問不在同一包中的保護變量
}
}
4.默認訪問變量
如果在變量前不加任何訪問權修飾符,它就具有默認的訪問控制特性,也稱為friendly變量。它和保護變量非常像,它只允許在同一個包中的其他類訪問, 即便是子類,如果和父類不在同一包中,也不能繼承默認變量(這是默認訪問變量和保護變量的唯一區別)。因為它限定了訪問權限只能在包中,所以也有人稱默認 訪問權限為包訪問權限。
默認訪問變量使用示例。
package onlyDemo; //本類定義在包中
public class declareDefault{
int defaultVar=10; //定義一個默認訪問變量
void change(){
defaultVar=20; //合法
}
}
onlyDemo包中的其他類,可以訪問defaultVar變量:
package onlyDemo;
public class otherClass{ //它也在包onlyDemo中
void change(){
declareDefault ca=new declareDefault();
ca.defaultVar=20; //合法
}
}
下面是它的子類,也在onlyDemo包中。它除了可以像包中其他類那樣通過"對象名.變量名"來訪問默認變量,還可以通過繼承的方式來訪問。
package onlyDemo;
public class deriveClass extends declareDefault{ //定義一個子類
void change(){
//合法,改變的是deriveClass從declarDefault中所繼承的defaultVar值
defaultVar=30;
}
}
如果子類不在onlyDemo包中,就不會繼承默認變量,也就無法像上面那樣來訪問。
import onlyDemo.declareDefault;
public class deriveClass extends declareDefault{ //定義一個子類
void change(){
defaultVar=30; //非法,這個變量沒有繼承下來
}
}