面向對象進階部分學習方法:
特點:
邏輯性沒有那么強,但是概念會比較多。
記憶部分重要的概念,理解課堂上講解的需要大家掌握的概念,多多練習代碼。
今日內容
-
復習回顧
-
static關鍵字
-
繼承
教學目標
- 能夠掌握static關鍵字修飾的變量調用方式
- 能夠掌握static關鍵字修飾的方法調用方式
- 知道靜態代碼塊的格式和應用場景
- 能夠寫出類的繼承格式
- 能夠說出繼承的特點
- 能夠區分this和super的作用
- 能夠說出方法重寫的概念
- 能夠說出方法重寫的注意事項
第一章 復習回顧
1.1 如何定義類
類的定義格式如下:
修飾符 class 類名 {// 1.成員變量(屬性)// 2.成員方法 (行為) // 3.構造方法 (初始化類的對象數據的) }
例如:
public class Student {// 1.成員變量public String name ;public char sex ; // '男' '女'public int age; }
1.2 如何通過類創建對象
類名 對象名稱 = new 類名();
例如:
Student stu = new Student();
1.3 封裝
1.3.1 封裝的步驟
1.使用 private
關鍵字來修飾成員變量。
2.使用public
修飾getter和setter方法。
1.3.2 封裝的步驟實現
-
private修飾成員變量
public class Student {private String name;private int age; }
-
public修飾getter和setter方法
public class Student {private String name;private int age; ?public void setName(String n) {name = n;} ?public String getName() {return name;} ?public void setAge(int a) {if (a > 0 && a <200) {age = a;} else {System.out.println("年齡非法!");}} ?public int getAge() {return age;} }
1.4 構造方法
1.4.1 構造方法的作用
在創建對象的時候,給成員變量進行初始化。
初始化即賦值的意思。
1.4.2 構造方法的格式
修飾符 類名(形參列表) {// 構造體代碼,執行代碼 }
1.4.3 構造方法的應用
首先定義一個學生類,代碼如下:
public class Student {// 1.成員變量public String name;public int age; ?// 2.構造方法public Student() {System.out.println("無參數構造方法被調用");} }
接下來通過調用構造方法得到兩個學生對象。
public class CreateStu02 {public static void main(String[] args) {// 創建一個學生對象// 類名 變量名稱 = new 類名();Student s1 = new Student();// 使用對象訪問成員變量,賦值s1.name = "張三";s1.age = 20 ; ?// 使用對象訪問成員變量 輸出值System.out.println(s1.name);System.out.println(s1.age); ?Student s2 = new Student();// 使用對象訪問成員變量 賦值s2.name = "李四";s2.age = 18 ;System.out.println(s2.name);System.out.println(s2.age);} }
1.5 this關鍵字的作用
1.5.1 this關鍵字的作用
this代表所在類的當前對象的引用(地址值),即代表當前對象。
1.5.2 this關鍵字的應用
1.5.2.1 用于普通的gettter與setter方法
this出現在實例方法中,誰調用這個方法(哪個對象調用這個方法),this就代表誰(this就代表哪個對象)。
public class Student {private String name;private int age; ?public void setName(String name) {this.name = name;} ?public String getName() {return name;} ?public void setAge(int age) {if (age > 0 && age < 200) {this.age = age;} else {System.out.println("年齡非法!");}} ?public int getAge() {return age;} }
1.5.2.2 用于構造方法中
this出現在構造方法中,代表構造方法正在初始化的那個對象。
public class Student {private String name;private int age;// 無參數構造方法public Student() {} // 有參數構造方法public Student(String name,int age) {this.name = name;this.age = age; } }
第二章 static關鍵字
2.1 概述
以前我們定義過如下類:
public class Student {// 成員變量public String name;public char sex; // '男' '女'public int age; ?// 無參數構造方法public Student() { ?}// 有參數構造方法public Student(String ?a) { ?} }
我們已經知道面向對象中,存在類和對象的概念,我們在類中定義了一些成員變量,例如name,age,sex ,結果發現這些成員變量,每個對象都存在(因為每個對象都可以訪問)。
而像name ,age , sex確實是每個學生對象都應該有的屬性,應該屬于每個對象。
所以Java中成員(變量和方法)等是存在所屬性的,Java是通過static關鍵字來區分的。static關鍵字在Java開發非常的重要,對于理解面向對象非常關鍵。
關于 static
關鍵字的使用,它可以用來修飾的成員變量和成員方法,被static修飾的成員是屬于類的是放在靜態區中,沒有static修飾的成員變量和方法則是屬于對象的。我們上面案例中的成員變量都是沒有static修飾的,所以屬于每個對象。
2.2 定義格式和使用
static是靜態的意思。 static可以修飾成員變量或者修飾方法。
2.2.1 靜態變量及其訪問
有static修飾成員變量,說明這個成員變量是屬于類的,這個成員變量稱為類變量或者靜態成員變量。 直接用 類名訪問即可。因為類只有一個,所以靜態成員變量在內存區域中也只存在一份。所有的對象都可以共享這個變量。
如何使用呢
例如現在我們需要定義傳智全部的學生類,那么這些學生類的對象的學校屬性應該都是“傳智”,這個時候我們可以把這個屬性定義成static修飾的靜態成員變量。
定義格式
修飾符 static 數據類型 變量名 = 初始值; ? ?
舉例
public class Student {public static String schoolName = "傳智播客"; // 屬于類,只有一份。// ..... }
靜態成員變量的訪問:
格式:類名.靜態變量
public static void ?main(String[] args){System.out.println(Student.schoolName); // 傳智播客Student.schoolName = "黑馬程序員";System.out.println(Student.schoolName); // 黑馬程序員 }
2.2.2 實例變量及其訪問
無static修飾的成員變量屬于每個對象的, 這個成員變量叫實例變量,之前我們寫成員變量就是實例成員變量。
需要注意的是:實例成員變量屬于每個對象,必須創建類的對象才可以訪問。
格式:對象.實例成員變量
2.2.3 靜態方法及其訪問
有static修飾成員方法,說明這個成員方法是屬于類的,這個成員方法稱為類方法或者靜態方法**。 直接用 類名訪問即可。因為類只有一個,所以靜態方法在內存區域中也只存在一份。所有的對象都可以共享這個方法。
與靜態成員變量一樣,靜態方法也是直接通過類名.方法名稱即可訪問。
舉例
public class Student{public static String schoolName = "傳智播客"; // 屬于類,只有一份。// .....public static void study(){System.out.println("我們都在黑馬程序員學習"); ? } }
靜態成員變量的訪問:
格式:類名.靜態方法
public static void ?main(String[] args){Student.study(); }
2.2.4 實例方法及其訪問
無static修飾的成員方法屬于每個對象的,這個成員方法也叫做實例方法。
需要注意的是:實例方法是屬于每個對象,必須創建類的對象才可以訪問。
格式:對象.實例方法
示例:
public class Student {// 實例變量private String name ;// 2.方法:行為// 無 static修飾,實例方法。屬于每個對象,必須創建對象調用public void run(){System.out.println("學生可以跑步");}// 無 static修飾,實例方法public ?void sleep(){System.out.println("學生睡覺");}public static void study(){} }
public static void main(String[] args){// 創建對象 Student stu = new Student ;stu.name = "徐干";// Student.sleep();// 報錯,必須用對象訪問。stu.sleep();stu.run(); }
2.3 小結
1.當 static
修飾成員變量或者成員方法時,該變量稱為靜態變量,該方法稱為靜態方法。該類的每個對象都共享同一個類的靜態變量和靜態方法。任何對象都可以更改該靜態變量的值或者訪問靜態方法。但是不推薦這種方式去訪問。因為靜態變量或者靜態方法直接通過類名訪問即可,完全沒有必要用對象去訪問。
2.無static修飾的成員變量或者成員方法,稱為實例變量,實例方法,實例變量和實例方法必須創建類的對象,然后通過對象來訪問。
3.static修飾的成員屬于類,會存儲在靜態區,是隨著類的加載而加載的,且只加載一次,所以只有一份,節省內存。存儲于一塊固定的內存區域(靜態區),所以,可以直接被類名調用。它優先于對象存在,所以,可以被所有對象共享。
4.無static修飾的成員,是屬于對象,對象有多少個,他們就會出現多少份。所以必須由對象調用。
第三章 繼承
3.1 概述
3.1.1 引入
假如我們要定義如下類: 學生類,老師類和工人類,分析如下。
-
學生類 屬性:姓名,年齡 行為:吃飯,睡覺
-
老師類 屬性:姓名,年齡,薪水 行為:吃飯,睡覺,教書
-
班主任 屬性:姓名,年齡,薪水 行為:吃飯,睡覺,管理
如果我們定義了這三個類去開發一個系統,那么這三個類中就存在大量重復的信息(屬性:姓名,年齡。行為:吃飯,睡覺)。這樣就導致了相同代碼大量重復,代碼顯得很臃腫和冗余,那么如何解決呢?
假如多個類中存在相同屬性和行為時,我們可以將這些內容抽取到單獨一個類中,那么多個類無需再定義這些屬性和行為,只要繼承那一個類即可。如圖所示:
其中,多個類可以稱為子類,單獨被繼承的那一個類稱為父類、超類(superclass)或者基類。
3.1.2 繼承的含義
繼承描述的是事物之間的所屬關系,這種關系是:is-a
的關系。例如,兔子屬于食草動物,食草動物屬于動物。可見,父類更通用,子類更具體。我們通過繼承,可以使多種事物之間形成一種關系體系。
繼承:就是子類繼承父類的屬性和行為,使得子類對象可以直接具有與父類相同的屬性、相同的行為。子類可以直接訪問父類中的非私有的屬性和行為。
3.1.3 繼承的好處
-
提高代碼的復用性(減少代碼冗余,相同代碼重復利用)。
-
使類與類之間產生了關系。
3.2 繼承的格式
通過 extends
關鍵字,可以聲明一個子類繼承另外一個父類,定義格式如下:
class 父類 {... } ? class 子類 extends 父類 {... }
需要注意:Java是單繼承的,一個類只能繼承一個直接父類,跟現實世界很像,但是Java中的子類是更加強大的。
3.3 繼承案例
3.3.1 案例
請使用繼承定義以下類:
-
學生類 屬性:姓名,年齡 行為:吃飯,睡覺
-
老師類 屬性:姓名,年齡,薪水 行為:吃飯,睡覺,教書
-
班主任 屬性:姓名,年齡,薪水 行為:吃飯,睡覺,管理
3.3.2 案例圖解分析
老師類,學生類,還有班主任類,實際上都是屬于人類的,我們可以定義一個人類,把他們相同的屬性和行為都定義在人類中,然后繼承人類即可,子類特有的屬性和行為就定義在子類中了。
如下圖所示。
3.3.3 案例代碼實現
1.父類Human類
public class Human {// 合理隱藏private String name ;private int age ;// 合理暴露public String getName() {return name;} ?public void setName(String name) {this.name = name;} ?public int getAge() {return age;} ?public void setAge(int age) {this.age = age;}}
2.子類Teacher類
public class Teacher extends Human {// 工資private double salary ;// 特有方法public void teach(){System.out.println("老師在認真教技術!");} ?public double getSalary() {return salary;} ?public void setSalary(double salary) {this.salary = salary;} }
3.子類Student類
public class Student extends Human{}
4.子類BanZhuren類
public class Teacher extends Human {// 工資private double salary ;// 特有方法public void admin(){System.out.println("班主任強調紀律問題!");}public double getSalary() {return salary;} ?public void setSalary(double salary) {this.salary = salary;} }
5.測試類
?public class Test {public static void main(String[] args) {Teacher dlei = new Teacher();dlei.setName("播仔");dlei.setAge("31");dlei.setSalary(1000.99);System.out.println(dlei.getName());System.out.println(dlei.getAge());System.out.println(dlei.getSalary());dlei.teach();BanZhuRen linTao = new BanZhuRen();linTao.setName("靈濤");linTao.setAge("28");linTao.setSalary(1000.99);System.out.println(linTao.getName());System.out.println(linTao.getAge());System.out.println(linTao.getSalary());linTao.admin(); ?Student xugan = new Student();xugan.setName("播仔");xugan.setAge("31");//xugan.setSalary(1000.99); // xugan沒有薪水屬性,報錯!System.out.println(xugan.getName());System.out.println(xugan.getAge()); ? ? ?}}
3.3.4 小結
1.繼承實際上是子類相同的屬性和行為可以定義在父類中,子類特有的屬性和行為由自己定義,這樣就實現了相同屬性和行為的重復利用,從而提高了代碼復用。
2.子類繼承父類,就可以直接得到父類的成員變量和方法。是否可以繼承所有成分呢?請看下節!
3.4 子類不能繼承的內容
3.4.1 引入
并不是父類的所有內容都可以給子類繼承的:
子類不能繼承父類的構造方法。
值得注意的是子類可以繼承父類的私有成員(成員變量,方法),只是子類無法直接訪問而已,可以通過getter/setter方法訪問父類的private成員變量。
3.4.1 演示代碼
public class Demo03 {public static void main(String[] args) {Zi z = new Zi();System.out.println(z.num1); // System.out.println(z.num2); // 私有的子類無法使用// 通過getter/setter方法訪問父類的private成員變量System.out.println(z.getNum2()); ?z.show1();// z.show2(); // 私有的子類無法使用} } ? class Fu {public int num1 = 10;private int num2 = 20; ?public void show1() {System.out.println("show1");} ?private void show2() {System.out.println("show2");} ?public int getNum2() {return num2;} ?public void setNum2(int num2) {this.num2 = num2;} } ? class Zi extends Fu { }
3.5 繼承后的特點—成員變量
當類之間產生了繼承關系后,其中各類中的成員變量,又產生了哪些影響呢?
3.5.1 成員變量不重名
如果子類父類中出現不重名的成員變量,這時的訪問是沒有影響的。代碼如下:
class Fu {// Fu中的成員變量int num = 5; } class Zi extends Fu {// Zi中的成員變量int num2 = 6;// Zi中的成員方法public void show() {// 訪問父類中的numSystem.out.println("Fu num="+num); // 繼承而來,所以直接訪問。// 訪問子類中的num2System.out.println("Zi num2="+num2);} } class Demo04 {public static void main(String[] args) {// 創建子類對象Zi z = new Zi(); // 調用子類中的show方法z.show(); ?} } ? 演示結果: Fu num = 5 Zi num2 = 6
3.5.2 成員變量重名
如果子類父類中出現重名的成員變量,這時的訪問是有影響的。代碼如下:
class Fu1 {// Fu中的成員變量。int num = 5; } class Zi1 extends Fu1 {// Zi中的成員變量int num = 6;public void show() {// 訪問父類中的numSystem.out.println("Fu num=" + num);// 訪問子類中的numSystem.out.println("Zi num=" + num);} } class Demo04 {public static void main(String[] args) {// 創建子類對象Zi1 z = new Zi1(); // 調用子類中的show方法z1.show(); } } 演示結果: Fu num = 6 Zi num = 6
子父類中出現了同名的成員變量時,子類會優先訪問自己對象中的成員變量。如果此時想訪問父類成員變量如何解決呢?我們可以使用super關鍵字。
3.5.3 super訪問父類成員變量
子父類中出現了同名的成員變量時,在子類中需要訪問父類中非私有成員變量時,需要使用super
關鍵字,修飾父類成員變量,類似于之前學過的 this
。
需要注意的是:super代表的是父類對象的引用,this代表的是當前對象的引用。
使用格式:
super.父類成員變量名
子類方法需要修改,代碼如下:
class Fu {// Fu中的成員變量。int num = 5; } ? class Zi extends Fu {// Zi中的成員變量int num = 6;public void show() {int num = 1;// 訪問方法中的numSystem.out.println("method num=" + num);// 訪問子類中的numSystem.out.println("Zi num=" + this.num);// 訪問父類中的numSystem.out.println("Fu num=" + super.num);} } ? class Demo04 {public static void main(String[] args) {// 創建子類對象Zi1 z = new Zi1(); // 調用子類中的show方法z1.show(); } } ? 演示結果: method num=1 Zi num=6 Fu num=5
小貼士:Fu 類中的成員變量是非私有的,子類中可以直接訪問。若Fu 類中的成員變量私有了,子類是不能直接訪問的。通常編碼時,我們遵循封裝的原則,使用private修飾成員變量,那么如何訪問父類的私有成員變量呢?對!可以在父類中提供公共的getXxx方法和setXxx方法。
3.6 繼承后的特點—成員方法
當類之間產生了關系,其中各類中的成員方法,又產生了哪些影響呢?
3.6.1 成員方法不重名
如果子類父類中出現不重名的成員方法,這時的調用是沒有影響的。對象調用方法時,會先在子類中查找有沒有對應的方法,若子類中存在就會執行子類中的方法,若子類中不存在就會執行父類中相應的方法。代碼如下:
class Fu {public void show() {System.out.println("Fu類中的show方法執行");} } class Zi extends Fu {public void show2() {System.out.println("Zi類中的show2方法執行");} } public ?class Demo05 {public static void main(String[] args) {Zi z = new Zi();//子類中沒有show方法,但是可以找到父類方法去執行z.show(); z.show2();} }
3.6.2 成員方法重名
如果子類父類中出現重名的成員方法,則創建子類對象調用該方法的時候,子類對象會優先調用自己的方法。
代碼如下:
class Fu {public void show() {System.out.println("Fu show");} } class Zi extends Fu {//子類重寫了父類的show方法public void show() {System.out.println("Zi show");} } public class ExtendsDemo05{public static void main(String[] args) {Zi z = new Zi();// 子類中有show方法,只執行重寫后的show方法z.show(); ?// Zi show} }
3.7 方法重寫
3.7.1 概念
方法重寫 :子類中出現與父類一模一樣的方法時(返回值類型,方法名和參數列表都相同),會出現覆蓋效果,也稱為重寫或者復寫。聲明不變,重新實現。
3.7.2 使用場景與案例
發生在子父類之間的關系。 子類繼承了父類的方法,但是子類覺得父類的這方法不足以滿足自己的需求,子類重新寫了一個與父類同名的方法,以便覆蓋父類的該方 法。
例如:我們定義了一個動物類代碼如下:
public class Animal {public void run(){System.out.println("動物跑的很快!");}public void cry(){System.out.println("動物都可以叫~~~");} }
然后定義一個貓類,貓可能認為父類cry()方法不能滿足自己的需求
代碼如下:
public class Cat extends Animal {public void cry(){System.out.println("我們一起學貓叫,喵喵喵!喵的非常好聽!");} } ? public class Test {public static void main(String[] args) {// 創建子類對象Cat ddm = new Cat();// 調用父類繼承而來的方法ddm.run();// 調用子類重寫的方法ddm.cry();} }
3.7.2 @Override重寫注解
-
@Override:注解,重寫注解校驗!
-
這個注解標記的方法,就說明這個方法必須是重寫父類的方法,否則編譯階段報錯。
-
建議重寫都加上這個注解,一方面可以提高代碼的可讀性,一方面可以防止重寫出錯!
加上后的子類代碼形式如下:
public class Cat extends Animal {// 聲明不變,重新實現// 方法名稱與父類全部一樣,只是方法體中的功能重寫寫了!@Overridepublic void cry(){System.out.println("我們一起學貓叫,喵喵喵!喵的非常好聽!");} }
3.7.3 注意事項
-
方法重寫是發生在子父類之間的關系。
-
子類方法覆蓋父類方法,必須要保證權限大于等于父類權限。
-
子類方法覆蓋父類方法,返回值類型、函數名和參數列表都要一模一樣。
3.8 繼承后的特點—構造方法
3.8.1 引入
當類之間產生了關系,其中各類中的構造方法,又產生了哪些影響呢? 首先我們要回憶兩個事情,構造方法的定義格式和作用。
-
構造方法的名字是與類名一致的。所以子類是無法繼承父類構造方法的。
-
構造方法的作用是初始化對象成員變量數據的。所以子類的初始化過程中,必須先執行父類的初始化動作。子類的構造方法中默認有一個
super()
,表示調用父類的構造方法,父類成員變量初始化后,才可以給子類使用。(先有爸爸,才能有兒子)
繼承后子類構方法器特點:子類所有構造方法的第一行都會默認先調用父類的無參構造方法
3.8.2 案例演示
按如下需求定義類:
-
人類 成員變量: 姓名,年齡 成員方法: 吃飯
-
學生類 成員變量: 姓名,年齡,成績 成員方法: 吃飯
代碼如下:
class Person {private String name;private int age; ?public Person() {System.out.println("父類無參");} ?// getter/setter省略 } ? class Student extends Person {private double score; ?public Student() {//super(); // 調用父類無參,默認就存在,可以不寫,必須再第一行System.out.println("子類無參");}public Student(double score) {//super(); // 調用父類無參,默認就存在,可以不寫,必須再第一行this.score = score; ? ?System.out.println("子類有參");} ? } ? public class Demo07 {public static void main(String[] args) {Student s1 = new Student();System.out.println("----------");Student s2 = new Student(99.9);} } ? 輸出結果: 父類無參 子類無參 ---------- 父類無參 子類有參
3.8.3 小結
-
子類構造方法執行的時候,都會在第一行默認先調用父類無參數構造方法一次。
-
子類構造方法的第一行都隱含了一個super()去調用父類無參數構造方法,super()可以省略不寫。
3.9 super(...)和this(...)
3.9.1 引入
請看上節中的如下案例:
class Person {private String name;private int age; ?public Person() {System.out.println("父類無參");} ?// getter/setter省略 } ? class Student extends Person {private double score; ?public Student() {//super(); // 調用父類無參構造方法,默認就存在,可以不寫,必須再第一行System.out.println("子類無參");}public Student(double score) {//super(); // 調用父類無參構造方法,默認就存在,可以不寫,必須再第一行this.score = score; ? ?System.out.println("子類有參");}// getter/setter省略 } ? public class Demo07 {public static void main(String[] args) {// 調用子類有參數構造方法Student s2 = new Student(99.9);System.out.println(s2.getScore()); // 99.9System.out.println(s2.getName()); // 輸出 nullSystem.out.println(s2.getAge()); // 輸出 0} }
我們發現,子類有參數構造方法只是初始化了自己對象中的成員變量score,而父類中的成員變量name和age依然是沒有數據的,怎么解決這個問題呢,我們可以借助與super(...)去調用父類構造方法,以便初始化繼承自父類對象的name和age.
3.9.2 super和this的用法格式
super和this完整的用法如下,其中this,super訪問成員我們已經接觸過了。
this.成員變量 ? -- ? ?本類的 super.成員變量 ? -- ? ?父類的 ? this.成員方法名() -- ? ?本類的 ? ? super.成員方法名() ? -- ? ?父類的
接下來我們使用調用構造方法格式:
super(...) -- 調用父類的構造方法,根據參數匹配確認 this(...) -- 調用本類的其他構造方法,根據參數匹配確認
3.9.3 super(....)用法演示
代碼如下:
class Person {private String name ="鳳姐";private int age = 20; ?public Person() {System.out.println("父類無參");}public Person(String name , int age){this.name = name ;this.age = age ;} ?// getter/setter省略 } ? class Student extends Person {private double score = 100; ?public Student() {//super(); // 調用父類無參構造方法,默認就存在,可以不寫,必須再第一行System.out.println("子類無參");}public Student(String name , int age,double score) {super(name ,age);// 調用父類有參構造方法Person(String name , int age)初始化name和agethis.score = score; ? ?System.out.println("子類有參");}// getter/setter省略 } ? public class Demo07 {public static void main(String[] args) {// 調用子類有參數構造方法Student s2 = new Student("張三",20,99);System.out.println(s2.getScore()); // 99System.out.println(s2.getName()); // 輸出 張三System.out.println(s2.getAge()); // 輸出 20} }
注意:
子類的每個構造方法中均有默認的super(),調用父類的空參構造。手動調用父類構造會覆蓋默認的super()。
super() 和 this() 都必須是在構造方法的第一行,所以不能同時出現。
super(..)是根據參數去確定調用父類哪個構造方法的。
3.9.4 super(...)案例圖解
父類空間優先于子類對象產生
在每次創建子類對象時,先初始化父類空間,再創建其子類對象本身。目的在于子類對象中包含了其對應的父類空間,便可以包含其父類的成員,如果父類成員非private修飾,則子類可以隨意使用父類成員。代碼體現在子類的構造七調用時,一定先調用父類的構造方法。理解圖解如下:
3.9.5 this(...)用法演示
this(...)
-
默認是去找本類中的其他構造方法,根據參數來確定具體調用哪一個構造方法。
-
為了借用其他構造方法的功能。
package com.itheima._08this和super調用構造方法; /*** this(...):* ? 默認是去找本類中的其他構造方法,根據參數來確定具體調用哪一個構造方法。* ? 為了借用其他構造方法的功能。**/ public class ThisDemo01 {public static void main(String[] args) {Student xuGan = new Student();System.out.println(xuGan.getName()); // 輸出:徐干System.out.println(xuGan.getAge());// 輸出:21System.out.println(xuGan.getSex());// 輸出: 男} } ? class Student{private String name ;private int age ;private char sex ; ?public Student() {// 很弱,我的兄弟很牛逼啊,我可以調用其他構造方法:Student(String name, int age, char sex)this("徐干",21,'男');} ?public Student(String name, int age, char sex) {this.name = name ;this.age = age ? ;this.sex = sex ? ;} ?public String getName() {return name;} ?public void setName(String name) {this.name = name;} ?public int getAge() {return age;} ?public void setAge(int age) {this.age = age;} ?public char getSex() {return sex;} ?public void setSex(char sex) {this.sex = sex;} }
3.9.6 小結
-
子類的每個構造方法中均有默認的super(),調用父類的空參構造。手動調用父類構造會覆蓋默認的super()。
-
super() 和 this() 都必須是在構造方法的第一行,所以不能同時出現。
-
super(..)和this(...)是根據參數去確定調用父類哪個構造方法的。
-
super(..)可以調用父類構造方法初始化繼承自父類的成員變量的數據。
-
this(..)可以調用本類中的其他構造方法。
3.10 繼承的特點
-
Java只支持單繼承,不支持多繼承。
// 一個類只能有一個父類,不可以有多個父類。 class A {} class B {} class C1 extends A {} // ok // class C2 extends A, B {} // error
-
一個類可以有多個子類。
// A可以有多個子類 class A {} class C1 extends A {} class C2 extends ?A {}
-
可以多層繼承。
class A {} class C1 extends A {} class D extends C1 {}
頂層父類是Object類。所有的類默認繼承Object,作為父類。
4. 關于今天知識的小結:
會寫一個繼承結構下的標準Javabean即可
需求:
貓:屬性,姓名,年齡,顏色
狗:屬性,姓名,年齡,顏色,吼叫
分享書寫技巧:
1.在大腦中要區分誰是父,誰是子
2.把共性寫到父類中,獨有的東西寫在子類中
3.開始編寫標準Javabean(從上往下寫)
4.在測試類中,創建對象并賦值調用
代碼示例:
package com.itheima.test4; ? public class Animal {//姓名,年齡,顏色private String name;private int age;private String color; ? ?public Animal() {} ?public Animal(String name, int age, String color) {this.name = name;this.age = age;this.color = color;} ?public String getName() {return name;} ?public void setName(String name) {this.name = name;} ?public int getAge() {return age;} ?public void setAge(int age) {this.age = age;} ?public String getColor() {return color;} ?public void setColor(String color) {this.color = color;} } ? ? public class Cat extends Animal{//因為貓類中沒有獨有的屬性。//所以此時不需要寫私有的成員變量 ?//空參public Cat() {} ?//需要帶子類和父類中所有的屬性public Cat(String name, int age, String color) {super(name,age,color);} } ? ? public class Dog extends Animal{//Dog :吼叫private String wang; ?//構造public Dog() {} ?//帶參構造:帶子類加父類所有的屬性public Dog(String name, int age, String color,String wang) {//共性的屬性交給父類賦值super(name,age,color);//獨有的屬性自己賦值this.wang = wang;} ?public String getWang() {return wang;} ?public void setWang(String wang) {this.wang = wang;} } ? public class Demo {public static void main(String[] args) {//Animal : 姓名,年齡,顏色//Cat ://Dog :吼叫 ?//創建狗的對象Dog d = new Dog("旺財",2,"黑色","嗷嗚~~");System.out.println(d.getName()+", " + d.getAge() + ", " + d.getColor() + ", " + d.getWang()); ?//創建貓的對象Cat c = new Cat("中華田園貓",3,"黃色");System.out.println(c.getName() + ", " + c.getAge() + ", " + c.getColor());} }