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