繼承后的特點——成員變數
物件訪問成員變數時,會先在子類中查找有沒有定義對應的變數,若子類中存在就會就近使用子類中的變數,若子類中沒有定義就會沿著繼承關系往上找有沒有定義相應的變數,若父類中也沒有則編譯不通過,代碼示例:
class Fu {
// Fu類中的成員變數,
int num = 5;
int num2 = 7;
}
class Zi extends Fu {
// Zi類中的成員變數
int num = 6;
public void show() {
// 訪問父類中的num2
System.out.println("num2=" + num2);
// 訪問子類中的num
System.out.println("num=" + num);
}
}
public class ExtendsDemo0 {
public static void main(String[] args) {
// 創建子類物件
Zi z = new Zi();
// 呼叫子類中的show方法
z.show();
}
}
演示結果:
num2=7
num=6
子父類中出現了同名的成員變數時,在子類中訪問父類中非私有成員變數,需要使用 super 關鍵字,用法類似于 this ,
使用格式:
super.父類成員變數名
代碼如下:
class Zi extends Fu {
// Zi類中的成員變數
int num = 6;
public void show() {
//訪問父類中的num
System.out.println("Fu num2=" + num2);
//訪問父類中的num
System.out.println("Fu num=" + super.num);
}
}
演示結果:
Fu num = 7
Zi num = 5
Fu 類中的私有成員變數,子類是不能直接訪問的,編碼時,遵循封裝的原則,使用private修飾成員變數,可以在父類中提供公共的getXxx方法和setXxx方法來訪問,
super和this
父類空間優先于子類物件產生
在每次創建子類物件時,先初始化父類空間,再創建其子類物件本身,目的在于子類物件中包含了其對應的父類空間,便可以包含其父類的成員,代碼體現在子類的構造方法呼叫時,一定先呼叫父類的構造方法,理解圖解如下:

super和this的含義
-
super :代表父類的存盤空間標識(可以理解為父類的參考),
-
this :代表當前物件的參考(誰呼叫就代表誰),
super和this的用法
this.成員變數 -- 本類的
super.成員變數 -- 父類的
this.成員方法名() -- 本類的
super.成員方法名() -- 父類的
代碼示例:
class Animal {
public void eat() {
System.out.println("animal : eat");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("cat : eat");
}
public void eatTest() {
this.eat(); // this 呼叫本類的方法
super.eat(); // super 呼叫父類的方法
}
}
public class ExtendsDemo08 {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Cat c = new Cat();
c.eatTest();
}
}
輸出結果為:
animal : eat
cat : eat
animal : eat
注意:
-
通過super參考屬性、方法、構造器時,都要求該成員是可見的,即該成員的修飾符不能是private的,跨包的話還不能是預設的,
-
super的追溯不僅限于直接父類
-
如果某個屬性或方法前面使用“this.”,那么先從本類中查找,如果未找到,會沿著繼承關系往上找
如果某個屬性或方法前面使用“super.”,那么先從直接父類中查找,如果未找到,會沿著繼承關系往上找
如果某個屬性或方法前面既沒有“this.”,也沒有“super.”,遵循就近原則,先從本類中查找,如果未找到,會沿著繼承關系往上找
繼承后的特點——成員方法
成員方法不重名時
如果子、父類中的方法不重名,這時的呼叫是沒有影響的,物件呼叫方法時,會先在子類中查找有沒有定義對應的方法,若子類中存在就執行子類中定義的方法,若子類中沒有定義就會沿著繼承關系往上找有沒有定義相應的方法,若父類中也沒有則編譯不通過,代碼示例:
class Fu{
public void show(){
System.out.println("Fu類中的show方法執行");
}
}
class Zi extends Fu{
public void show2(){
System.out.println("Zi類中的show2方法執行");
}
}
public class ExtendsDemo04{
public static void main(String[] args) {
Zi z = new Zi();
//子類中沒有定義show方法,但是可以找從父類繼承的show方法去執行
z.show();
z.show2();
}
}
成員方法重名——重寫(Override)
如果子、父類中出現重名的成員方法,這時的訪問是一種特殊情況,叫做方法重寫 (Override),
- 方法重寫 :子類繼承了父類,可以獲得父類的成員變數和成員方法;可是當父類的某個方法不適合于子類本身的特征時,在子類中可以根據需要對從父類中繼承來的方法進行改造,也稱為方法的重寫、覆寫,在程式執行時,子類的方法將覆寫父類的方法,
代碼如下:
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
}
}
重寫的應用
子類可以根據需要,定義特定于自己的行為,既沿襲了父類的功能名稱,又根據子類的需要重新實作父類方法,從而進行擴展增強,比如新的手機增加來電顯示頭像的功能,代碼如下:
class Phone {
public void sendMessage(){
System.out.println("發短信");
}
public void call(){
System.out.println("打電話");
}
public void showNum(){
System.out.println("來電顯示號碼");
}
}
//智能手機類
class NewPhone extends Phone {
//重寫父類的來電顯示號碼功能,并增加自己的顯示姓名和圖片功能
public void showNum(){
//呼叫父類已經存在的功能使用super
super.showNum();
//增加自己特有顯示姓名和圖片功能
System.out.println("顯示來電姓名");
System.out.println("顯示頭像");
}
}
public class ExtendsDemo06 {
public static void main(String[] args) {
// 創建子類物件
NewPhone np = new NewPhone();
// 呼叫父類繼承而來的方法
np.call();
// 呼叫子類重寫的方法
np.showNum();
}
}
重寫時,用到super.父類成員方法,表示呼叫父類的成員方法,
方法重寫注意事項
-
方法名:必須完全一致
-
形參串列:必須完全一致
-
回傳值型別:
如果是基本資料型別和void,必須一致
如果是參考資料型別,重寫的方法的回傳值型別 <= 被重寫方法的回傳值型別,Student<Person
-
修飾符:重寫的方法的修飾符范圍 >= 被重寫方法的修飾符范圍(public > protected > 預設 > private)
-
被重寫方法不能被
private、static、final修飾,如果跨包的話,修飾符預設的也不能被重寫,因為預設的跨包不可見
繼承后的特點——構造方法
首先我們要回憶兩個事情,構造方法的定義格式和作用:
- 構造方法的名字是與類名一致的,所以子類是無法繼承父類構造方法的,
- 構造方法的作用是初始化成員變數的,所以子類的初始化程序中,必須先執行父類的初始化動作,
- 子類不會繼承父類的構造器,但是一定會呼叫父類的構造器
- 默認情況下,呼叫的是父類的無參構造,super()寫或不寫都會呼叫父類的無參構造,如果要寫,必須在子類構造器首行
- 如果父類沒有無參構造,必須在子類的構造器首行使用super(實參串列)顯式呼叫父類的有參構造,否則編譯報錯
- super([形參串列]) 和 this([形參串列]) 都必須是在構造方法的第一行,所以不能同時出現,
代碼示例:
class Father{
public Father(){
System.out.println("父類的無參構造");
}
}
class Son extends Father{
private String str;
private int num;
public Son(){
//隱含呼叫了super(); 子類的構造器中一定會呼叫父類的構造器,默認呼叫父類的無參構造
System.out.println("子類的無參構造");
}
public Son(String str){
//隱含呼叫了super()
this.str = str;
System.out.println("子類的有參構造1");
}
public Son(String str,int num){
//呼叫多載的構造器,隱含呼叫了super()
this(str);
this.num = num;
System.out.println("子類的有參構造2");
}
}
public class ConstructorTest {
public static void main(String[] args) {
Son s1 = new Son();
/*
父類的無參構造
子類的無參構造
*/
//Son s2 = new Son("java");
/*
父類的無參構造
子類的有參構造1
*/
Son s3 = new Son("java", 10);
/*
父類的無參構造
子類的有參構造1
子類的有參構造2
*/
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/73379.html
標籤:Java
上一篇:Java自學-圖形界面 選單
