Java?的訪問(wèn)修飾符public,protected,private(封裝、繼承)
一、訪問(wèn)控制修飾符
Access level modifiers determine whether other classes can use a particular field or invoke a particular method.
訪問(wèn)級(jí)別修飾符決定其他類(lèi)是否可以使用特定成員變量或調(diào)用特定成員方法方法。
Java 中有 4 個(gè)級(jí)別的訪問(wèn)控制:
- public: 在所有類(lèi)中都是可見(jiàn)的
- protected: 僅在自己的包中、自己的子類(lèi)中可見(jiàn)
- package-private(沒(méi)有修飾符): 僅在自己的包中可見(jiàn)
- private: 僅在自己的類(lèi)中可見(jiàn)
修飾符 | Class | Package | Subclass | World |
---|---|---|---|---|
public | ?? | ?? | ?? | ?? |
protected | ?? | ?? | ?? | ? |
package-private | ?? | ?? | ? | ? |
private | ?? | ? | ? | ? |
- 這四個(gè)訪問(wèn)控制修飾符可以修飾類(lèi)的成員【eg:成員變量、成員方法、嵌套類(lèi)(Nested Class)】
- 只有 public 和 package-private(沒(méi)有修飾符)可以修飾頂級(jí)類(lèi)(Top-level Class)【頂級(jí)類(lèi)可以有多個(gè),但被 public 修飾的頂級(jí)類(lèi)只能有一個(gè)】
public class Person { public class Fahter { class Son { protected class Grandson { private class Dog { } } } } }
上面代碼中的 Person 就是頂級(jí)類(lèi),Person 類(lèi)(頂級(jí)類(lèi))只能被 public 修飾、或沒(méi)有訪問(wèn)修飾符
訪問(wèn)修飾符不能修飾局部類(lèi)(Local Class)、局部變量
二、封裝(Encapsulation)
- 類(lèi)中的成員變量私有化(private)
- 提供公共的(public)方法【Getter 和 Setter】讓外界操縱成員變量
public class Person { // 成員變量私有化 private String name; private int age; /* 提供公共的(public)方法(Getter 和 Setter)讓外界操縱私有的屬性 */ public String getName() { return name; } public int getAge() { return age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } }
public class Main { public static void main(String[] args) { Person p = new Person(); /* 通過(guò)公共的 Getter/Setter 方法操作成員變量 */ p.setName("張浩男"); p.setAge(11); System.out.println(p.getName()); System.out.println(p.getAge()); } }
?? 封裝避免外界直接修改屬性(而是通過(guò) Setter 方法修改屬性),把實(shí)現(xiàn)細(xì)節(jié)封裝起來(lái);Setter 可對(duì)數(shù)據(jù)進(jìn)行驗(yàn)證,保證數(shù)據(jù)安全合理
三、繼承(Inheritance)
(1) 引出繼承
學(xué)生類(lèi):
????
public class Student { private String name; private int age; private double score; private String gender; }
員工類(lèi):
????
public class Employee { private String name; private int age; private String gender; private double salary; }
- 上面代碼中的員工類(lèi)和學(xué)生類(lèi)都有 name、age 和 gender 屬性,員工類(lèi)和學(xué)生類(lèi)唯一不同的屬性是 salary 和 score
- 可以把 name、age 和 gender 等三個(gè)屬性也抽取在一個(gè)類(lèi)(Person)中,把 name、age 和 gender 作為 Person 類(lèi)的屬性。然后學(xué)生類(lèi)和員工類(lèi)繼承 Person 類(lèi)。這樣學(xué)生類(lèi)和員工類(lèi)也擁有了 Person 類(lèi)的 name、age 和 gender 等三個(gè)屬性,而學(xué)生類(lèi)和員工類(lèi)中可編寫(xiě)它們獨(dú)有的屬性。
人類(lèi)【包含 name、age 和 gender 三個(gè)屬性(這三個(gè)屬性是員工類(lèi)和學(xué)生類(lèi)也共有的)】
public class Person { private String name; private int age; private String gender; }
學(xué)生類(lèi)【獨(dú)有的屬性只有 score】
public class Student { private double score; }
員工類(lèi)【獨(dú)有的屬性只有 salary】
public class Student { private double salary; }
- Person 類(lèi)擁有 Student 類(lèi)和 Employee 類(lèi)共有的屬性(name、age、gender)
- 可使用 extends 關(guān)鍵字把 Person 類(lèi)和 Student 類(lèi)、把 Person 類(lèi)和 Employee 類(lèi)產(chǎn)生關(guān)聯(lián)(讓 Student 類(lèi)和 Employee 類(lèi)中也擁有 Person 類(lèi)中所擁有的屬性)
(2) 繼承介紹
The idea of inheritance(繼承) is simple but powerful: When you want to create a new class and there is already a class that includes some of the code that you want, you can derive(產(chǎn)生、獲得) your new class from the existing class. In doing this, you can reuse the fields and methods of the existing class without having to write them yourself.
繼承思想簡(jiǎn)單,卻強(qiáng)大:當(dāng)你想要?jiǎng)?chuàng)建一個(gè)新的類(lèi)的時(shí)候。如果有一個(gè)已存在的類(lèi),該類(lèi)中包含你的新類(lèi)中所需要的代碼。你可以從已存在的類(lèi)中產(chǎn)生你的新類(lèi)。這樣做的話,你就可以重復(fù)使用已存在的類(lèi)中的成員變量和成員方法,而無(wú)需自己重新寫(xiě)。
A subclass(子類(lèi)) inherits all the members (fields, methods, and nested classes) from its superclass(父類(lèi)、超類(lèi)). Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.
子類(lèi)繼承了父類(lèi)(或超類(lèi))中的所有成員(成員變量、成員方法和嵌套類(lèi))。構(gòu)造方法不是成員,所以構(gòu)造方法不會(huì)被子類(lèi)繼承,但父類(lèi)(或超類(lèi))的構(gòu)造方法可以被子類(lèi)調(diào)用。
繼承可實(shí)現(xiàn)代碼的復(fù)用。當(dāng)多個(gè)類(lèi)中存在相同的屬性和方法時(shí),可以從這些類(lèi)中抽象出父類(lèi),在父類(lèi)中定義這些相同的屬性和方法。然后所有的子類(lèi)不需要重新定義這些屬性和方法,只需要通過(guò) extends 關(guān)鍵字來(lái)繼承父類(lèi)即可。
public class Person { private String name; private int age; private String gender; }
// Student 類(lèi)繼承 Person 類(lèi) public class Student extends Person { private double score; }
// Employee 類(lèi)繼承 Person 類(lèi) public class Employee extends Person { private double salary; }
- Person 可叫做超類(lèi)、父類(lèi)、基類(lèi)
- Student 和 Employee 可叫做子類(lèi)或派生類(lèi)
(3) 繼承細(xì)節(jié)
?? ① 子類(lèi)繼承了父類(lèi)的成員變量和成員方法后,非私有的(public、protected、package-private)屬性和方法可以在子類(lèi)直接訪問(wèn)。私有的屬性和方法子類(lèi)不能夠直接訪問(wèn),可通過(guò)非私有的方法間接訪問(wèn)。父類(lèi) Father:
/** * 父類(lèi) */ public class Father { public String name = "父類(lèi) name"; protected String age = "父類(lèi) age"; String money = "父類(lèi) money"; // 被 private 修飾的屬性無(wú)法被子類(lèi)直接訪問(wèn)到 private String hobby = "父類(lèi) hobby"; public String getHobbyByPublic() { return hobby + "_ByPublic"; } protected String getHobbyByProtected() { return hobby + "_ByProtected"; } String getHobbyByPackagePrivate() { return hobby + "_ByPackagePrivate"; } }
子類(lèi) Son 繼承 Father:
/** * 子類(lèi) */ public class Son extends Father { public static void main(String[] args) { Son son = new Son(); son.printFatherClassFields(); } private void printFatherClassFields() { // output: 父類(lèi) name System.out.println(name); // output: 父類(lèi) age System.out.println(age); // output: 父類(lèi) money System.out.println(money); // 無(wú)法訪問(wèn)到父類(lèi)被 private 關(guān)鍵字修飾的屬性 // System.out.println(hobby); // ERROR // 可通過(guò)父類(lèi)的非私有的方法間接訪問(wèn)到父類(lèi)被 private 關(guān)鍵字修飾的屬性 // output: 父類(lèi) hobby_ByPublic System.out.println(getHobbyByPublic()); // output: 父類(lèi) hobby_ByProtected System.out.println(getHobbyByProtected()); // output: 父類(lèi) hobby_ByPackagePrivate System.out.println(getHobbyByPackagePrivate()); } }
?? ② 實(shí)例化子類(lèi)的時(shí)候,先調(diào)用父類(lèi)的構(gòu)造器完成父類(lèi)的初始化,后調(diào)用子類(lèi)的構(gòu)造器完成子類(lèi)的初始化 【“父子”,“父子”,先初始化“父”,后初始化“子”】
/** * 父類(lèi) */ public class Father { public Father() { // 父類(lèi)構(gòu)造器 System.out.println("1.public Father() 構(gòu)造器"); } }
/** * 子類(lèi) */ public class Son extends Father { public Son() { // 子類(lèi)構(gòu)造器 System.out.println("2.public Son() 構(gòu)造器"); } public static void main(String[] args) { new Son(); /* output: 1.public Father() 構(gòu)造器 2.public Son() 構(gòu)造器 */ } }
③ 創(chuàng)建子類(lèi)對(duì)象的時(shí)候,不管使用子類(lèi)的哪個(gè)構(gòu)造器,默認(rèn)情況下都會(huì)先去調(diào)用父類(lèi)的無(wú)參構(gòu)造器。如果父類(lèi)沒(méi)有提供無(wú)參構(gòu)造器,則子類(lèi)的構(gòu)造器中必須用 super 關(guān)鍵字去指定使用父類(lèi)的哪個(gè)構(gòu)造器。否則,編譯無(wú)法通過(guò)。
④ 子類(lèi)可通過(guò) super(參數(shù)列表) 顯示調(diào)用父類(lèi)的某個(gè)構(gòu)造器
⑤ super 使用的時(shí)候必須放在構(gòu)造器第一行,且 super 只能在構(gòu)造器中使用
⑥ super()
和 this()
都只能放在構(gòu)造器的第一行,所以這兩個(gè)方法不能在一個(gè)構(gòu)造器中同時(shí)存在
⑦ Java 中所有的類(lèi)都有一個(gè)共同的父類(lèi) Object
;Java 中所有的類(lèi)都是 Object
類(lèi)的子類(lèi);Object
類(lèi)是所有類(lèi)的基類(lèi)】
public class Father { public static void main(String[] args) { // output: class java.lang.Object // Father 類(lèi)繼承 Object 類(lèi) System.out.println(Father.class.getSuperclass()); } }
⑧ 父類(lèi)構(gòu)造器的調(diào)用不僅限于直接父類(lèi),將會(huì)一直往上追溯,直到 Object 類(lèi)
public class Grandpa { public Grandpa() { System.out.println("1. class Grandpa - 構(gòu)造器"); } }
public class Father extends Grandpa{ public Father() { System.out.println("2. class Father extends Grandpa - 構(gòu)造器"); } }
public class Son extends Father { public Son() { System.out.println("3. class Son extends Father - 構(gòu)造器"); } }
public class Grandson extends Son { public Grandson() { System.out.println("4. class Grandson extends Father - 構(gòu)造器"); } public static void main(String[] args) { new Grandson(); } }
output: 1. class Grandpa - 構(gòu)造器 2. class Father extends Grandpa - 構(gòu)造器 3. class Son extends Father - 構(gòu)造器 4. class Grandson extends Father - 構(gòu)造器
⑨ Java 中是單繼承機(jī)制(子類(lèi)最多只能繼承一個(gè)直接父類(lèi))
思考:如何讓 A 類(lèi)繼承 B 類(lèi)和 C 類(lèi) ?
A extends B;B extends C
public class C { public String candy = "candy"; }
public class B extends C { public String boy = "boy"; }
public class A extends B { public static void main(String[] args) { A a = new A(); a.test(); } private void test() { // boy System.out.println(boy); // candy System.out.println(candy); } }
到此這篇關(guān)于Java 的訪問(wèn)修飾符public,protected,private(封裝、繼承)的文章就介紹到這了,更多相關(guān)Java 訪問(wèn)修飾符內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Nacos設(shè)置為windows自啟動(dòng)服務(wù)的步驟詳解
這篇文章給大家介紹了Nacos設(shè)置為windows自啟動(dòng)服務(wù)的操作步驟,文中通過(guò)代碼示例和圖文結(jié)合講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-12-12Spring?AOP實(shí)現(xiàn)多數(shù)據(jù)源動(dòng)態(tài)切換
本文主要介紹了Spring?AOP實(shí)現(xiàn)多數(shù)據(jù)源動(dòng)態(tài)切換,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03java實(shí)現(xiàn)掃雷游戲控制臺(tái)版
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)掃雷游戲控制臺(tái)版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04源碼解析Spring 數(shù)據(jù)庫(kù)異常抽理知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家分享了關(guān)于源碼解析Spring 數(shù)據(jù)庫(kù)異常抽理知識(shí)點(diǎn)內(nèi)容,對(duì)此有需要的朋友們學(xué)習(xí)參考下。2019-05-05SpringBoot集成消息隊(duì)列的項(xiàng)目實(shí)踐
本文主要介紹了SpringBoot集成消息隊(duì)列的項(xiàng)目實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-02-02