不知道大家在平時的開發過程中有沒有注意到訪問修飾符,哈哈哈,有沒有懵,在java中有哪些訪問修飾符,還記得清嗎?今天想分享下訪問修飾符的哪些小事。
一、訪問修飾符有哪些
在java中提到訪問修飾符,大家可能都不陌生,但對於訪問修飾符我還是想再重申下,這些看似很普通的概念,在多年後的某個瞬間總能激起我們某些想法。
java中說白了就三種元素:類、方法、屬性,由這三種元素組合成了我們平時使用的API,來標識這三種元素的訪問許可權的字元就是訪問修飾符,通俗點理解就是我有一個方法我只想自己自己知道,我不想別人知道那麼我給它一個標識private,代表是私有的,那麼別人就無法訪問了,如果我想讓方圓5公里的人知道,我給它個標識protected,那麼就只有方圓5公里的人知道。訪問修飾符就是來控制類、方法、屬性的訪問範圍的。
在java中有四種訪問修飾符,分別是public、protected、default、private。上面說到java中有類、方法、屬性,下面看下這幾種訪問修飾符怎麼起作用的。
先上一張圖,讓大家有個大體的印象,
1.1、public
public,公開的,公共的。可以修飾類、方法、屬性。在修飾類的時候,一個.java檔案中只能有一個類是公共的,且和.java檔案同名;重點看下最後這句話,
看到了吧,在idea中給的提示很明確,Teacher是公共的(public),應該宣告到一個檔名為Teacher.java的檔案中。其實也很容易理解,在一個.java檔案中有多個公共的class,是無法區分哪個是主類的,所以在一個.java檔案中只能有一個公共的類。遺留一個小問題,在一個public的類中可以有其他修飾符修飾的類嗎?後面揭曉。
public修飾方法和屬性,想必不用我多說了,在平時使用的比較多,public修飾方法和屬性不受包的限制,在任何包中均可訪問。
1.2、protected
protected,受保護的。可以修飾內部類、方法、屬性。這裡有個概念是內部類,當然和內部類相對應的就是外部類,所謂內部類就是在一個外部類中的類,外部類就是平時我們寫的類,其類名和檔名一樣。一個例子如下,
package com.example.day04;
/**
Teacher是外部類
*/
public class Teacher {
/**
* Inner是內部類
*/
protected class Inner{
}
}
重點來看下protected修飾的方法和屬性,
package com.example.day04;
/**
Teacher是外部類
*/
public class Teacher {
protected String name;
protected void method(){
System.out.println(this.name);
}
}
那麼name和method()方法可以被哪些類訪問吶?看下本包中的類,
package com.example.day04;
public class TeacherA {
public static void main(String[] args) {
Teacher teacher=new Teacher();
teacher.name="tom";
teacher.method();
}
}
protected修飾的方法、屬性可以被本包中的類訪問,再來看下本包中的子類,
package com.example.day04;
public class TeacherB extends Teacher{
public static void main(String[] args) {
TeacherB teacherB=new TeacherB();
teacherB.name="tom";
teacherB.method();
}
}
列印結果如下,
tom
Process finished with exit code 0
protected修飾的方法、屬性可以被本包中的子類訪問,再來看下不同包中的類,
protected修飾的方法、屬性不可以被不同包中的類訪問,那麼不同包的子類吶?
package cn.example.day04;
import com.example.day04.Teacher;
public class TeacherD extends Teacher {
public static void main(String[] args) {
TeacherD teacherD=new TeacherD();
teacherD.name="tome";
teacherD.method();
}
}
結果如下,
tome
Process finished with exit code 0
protected修飾的方法、屬性可以被不同包中的子類訪問。
總結:protected修飾的屬性和方法可以被同包中的類、子類訪問;可以被不同包的子類訪問,不可以被不同包的類訪問。
1.3、default
這裡說default其實不是那麼嚴格,在java中不寫訪問修飾符,就是default,稱為default只為了好記,其實沒有“default”這個訪問修飾符。
default,預設的訪問修飾符。可以用來修飾類、屬性、方法。
有default修飾的類、屬性、方法,
package com.example.day04;
class Address {
String name;
void method(){
System.out.println(name);
}
}
在本包下的類,
package com.example.day04;
public class AddressA {
public static void main(String[] args) {
Address address=new Address();
address.name="china";
address.method();
}
}
結果如下,
china
Process finished with exit code 0
預設情況下的訪問修飾符,在本包下的類是可以訪問的。看下在本包下的子類,
package com.example.day04;
public class AddressB extends Address{
public static void main(String[] args) {
Address address=new Address();
address.name="china";
address.method();
}
}
看程式碼正常編譯未出錯,肯定是可以的。
預設情況下的訪問修飾符,在本包下的子類是可以訪問的。不同包下的類和子類,這裡不再一一列出例子了,直接給出下面的結論,
預設情況下的訪問修飾符,在不同包下的類、子類都是不可以訪問的預設修飾符修飾的類、屬性、方法。
總結,預設情況下的訪問修飾符,在本包下的類、子類是可以訪問的;在不同包下的類、子類都是不可以訪問
1.4、private
private,私有的。可以修飾類、屬性、方法。
在private修飾類時,不可以修飾外部類,可以修飾內部類。重點看下修飾的屬性、方法,這個是我們在平時開發中用的最多的。
這裡有一個使用private修飾的屬性、方法,
package com.example.day04;
public class Person {
private String name;
private void method(){
System.out.println(name);
}
private class A{
}
}
看下圖,在本包中,
private修飾的屬性、方法在本包中的類中是無法訪問的。看下在本包的子類吶?
private修飾的屬性、方法在本包的子類中是無法訪問的。
總結,private修飾的屬性、方法在本包中的類、子類是無法訪問的,在不同包的類、子類是無法訪問的。
二、一些小趣事
上面說了很多乏味的基礎知識,在日常的開發中你可能都意識不到天天在用。下面看一下幾個有意思的小問題。
2.1、一個public修飾的類中可以有其他類嗎
我們知道一個public修飾的類的類名和.java檔名是一樣的,那麼在這個類中還可以有其他類嗎?
從上圖中可以看到,一個public修飾的類中僅可以有預設修飾符修飾的類,protected、private修飾的均不可以,public修飾的也不可以哦。
2.2、protected方法存在的意義
protected修飾的方法可以在本包類、子類、不同包的子類訪問。這種方法存在的意義是什麼吶?在繼承中,子類可以訪問父類的protected方法,既然是繼承了,那麼沒繼承的類便不可訪問,protected很好的詮釋了繼承的意義。平時開發中使用protected方法是在抽象類中的抽象方法。
package com.example.day04;
/**
* 抽象的Car工廠
*/
public abstract class AbstractCarFactory {
protected abstract void generateCar();
}
那麼子類需要去覆蓋該抽象方法,非子類不需要覆蓋該方法,所以這個方法是protected訪問修飾符修飾的。有人會說是public修飾的可以嗎?當然可以,但是許可權肯定是越小越好啊,
package com.example.day04;
public class BiyadiCarFactroy extends AbstractCarFactory{
@Override
public void generateCar() {
System.out.println("generate biyadi car");
}
}
在子類中還可以改變覆蓋方法的訪問修飾符。
2.3、有了private為什麼還要public
在開發中寫的最多的可能就是類似下面的實體類,
package com.example.day04;
public class Address {
private String name;
private String code;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
Address類中屬性是private,而getXXX和setXXX方法是public,這是為了保護屬性,方式使用例項.屬性的方式進行設定/獲取值,而是通過其提供的setXXX/getXXX方法來設定/獲取值。通過方法的方式,可以在設定值的過程中對值進行校驗、判斷等操作,而直接通過例項.屬性的方式則無法完成上面的操作,只不過在日常的開發中,都是直接賦值,沒有進行校驗、判斷等其他操作而已。例下方,
public void setName(String name) {
System.out.println("設定name的值為:"+name);
if(name.equals("china")){
this.name = name;
}
System.out.println("設定完成");
}
2.4、子類無法訪問父類的私有屬性嗎
上面我們知道在子類中是無法訪問父類的私有屬性的,因為屬性是私有的即使子類也是無法訪問的。但我依然可以訪問到,
我們直接無法訪問到name屬性,但是我們可以通過其暴露的getXXX方法啊。
三、總結
本文分享了在平時開發中很容易忽略的一個點,就是訪問修飾符,我們平時用的最多的要屬public、private,但是為什麼要使用,這樣使用的好處是什麼。有人說一個專案中都是自己專案內的人,沒必要考慮訪問修飾符,我直接都用public不是更好,這樣也沒錯,但是這樣帶來的後果是沒有任何的訪問限制,類比生活中人人都是想怎麼幹就怎麼幹,想去什麼地方就去什麼地方,這樣豈不是沒了規則,這個社會是不是無法正常運轉了。到了程式中雖然沒有那麼嚴重,但是遵循一定的原則,對程式碼的整體設計後續的擴充套件性也是好的。本文只是想做個引子,提醒小夥伴們日常的開發中多思考,多嘗試。