Java學習筆記12---父類的對象引用指向子類對象,學習筆記12---

來源:互聯網
上載者:User

Java學習筆記12---父類的對象引用指向子類對象,學習筆記12---

當父類的對象引用沒有指向父類的對象,而是指向了子類的對象時,調用方法或訪問變數時會怎樣呢?

假設父類為Person,子類為Student,有下面的兩行定義:

Student sTest = new Student();

Person pTest = sTest;

其中,pTest就是父類的對象引用,sTest是子類的對象引用;pTest和sTest都指向了一個子類對象。那麼,

(1).如果子類的成員變數與父類的成員變數的類型及名稱都相同,則用sTest訪問時,訪問到的是子類的成員變數;用pTest訪問時,訪問到的是父類的成員變數;

(2).如果子類的靜態成員變數與父類的靜態成員變數的類型及名稱都相同,則用sTest訪問時,訪問到的是子類的靜態成員變數;用pTest訪問時,訪問到的是父類的靜態成員變數;

(3).如果子類的靜態方法重寫了父類的靜態方法,則用sTest調用時,調用的是子類的靜態成員方法;用pTest調用時,調用的是父類的靜態方法;(1),(2),(3)都稱為隱藏;

(4).如果子類的成員方法重寫了父類的成員方法,則用sTest調用時,調用到的是子類的成員方法;用pTest調用時,調用的也是子類的成員方法;此時稱為覆蓋;

(5).用sTest調用未覆蓋的父類成員方法時,該方法中如果使用到了被隱藏的變數或方法時,規則同上;

 

還是以簡單的樣本來詳細說明。

Person類為父類,Student類為子類,TestMain類為測試類別。代碼分別如下:

Person類的代碼為:

package human;public class Person {    String name;    int age;    String gender;        public String education;    private String hobby;    protected String residence;        static String citizenship = "Chinese";        public Person() {            }    public void setName(String n) {        this.name = n;    }    public String getName() {        return name;    }    public void informationPrint() {        System.out.println("My name is(getName) " + getName());        System.out.println("My name is(name) " + name);        System.out.println("I am " + getAge() + " years old");                if(getGender() == "female")            System.out.println("I am a girl");        else            if(getGender() == "male")                System.out.println("I am a boy");            else                System.out.println("Something is wrong!");        System.out.println("My hobby is " + hobby);                if(citizenship == "Chinese")            System.out.println("I am a chinese");        //test:靜態變數是否在構造方法之前初始化        else            if(citizenship == "US")                System.out.println("I am an American");            else                System.out.println("Oh,something is wrong");    }        //test:覆蓋    public void testModifierPublic() {        System.out.println("Person:Public");    }        //test:隱藏    public static void staMethodHide() {        System.out.println("Person:static Method");    }    }

 

Student類的代碼為:

package human;public class Student extends Person {    String stuNumber;    int score;        //test:隱藏    String name = "ha";    static String citizenship = "US";          public Student() {            }        public Student(String n, String g) {        super(n,g);    }        //test:隱藏    public void setName(String n) {        this.name = n;    }        //test:隱藏    public String getName() {        return name;    }            //test:覆蓋    public void testModifierPublic() {        System.out.println("Student:Public");    }        //test:super    public void testSuper() {        System.out.println("Super:");        super.testModifierPublic();    }        //test:隱藏    public static void staMethodHide() {        System.out.println("Student:static Method");    }}

  

TestMain類的代碼為:

package human;public class TestMain {    public static void main(String[] args) {        Student sTest = new Student();        Person pTest = sTest;                System.out.println("下面是以子類對象sTest來訪問變數、調用方法的結果:");        sTest.testModifierPublic();        System.out.println(sTest.name);        System.out.println(sTest.getName());        System.out.println(sTest.citizenship);        sTest.staMethodHide();        sTest.testSuper();        sTest.informationPrint();                System.out.println("下面是以父類對象pTest來訪問變數、調用方法的結果:");        pTest.testModifierPublic();        System.out.println(pTest.name);        System.out.println(pTest.getName());        System.out.println(pTest.citizenship);        pTest.staMethodHide();    }}

 

輸出結果為:

 1 下面是以子類對象sTest來訪問變數、調用方法的結果: 2 Student:Public 3 ha 4 Student:getName() 5 ha 6 US 7 Student:static Method 8 Super: 9 Person:Public10 Student:getName()11 My name is(getName) ha12 My name is(name) null13 I am 0 years old14 Something is wrong!15 My hobby is null16 I am a chinese17 下面是以父類對象pTest來訪問變數、調用方法的結果:18 Student:Public19 null20 Student:getName()21 ha22 Chinese23 Person:static Method
View Code

 

下面對結果進行分析:

(1).前兩條語句為:

Student sTest = new Student();
Person pTest = sTest;

第一條語句定義了子類對象引用sTest,並指向了一個子類對象;第二條語句定義了父類對象引用pTest,並被賦值為sTest的值;大體的記憶體結構見圖1:

                                                                  圖1

 

其中,子類的String型成員變數name與父類的name重名,子類的name值為“ha”,父類的name預設初始化為NULL;String型靜態成員變數citizenship與父類的citizenship重名,子類的citizenship值為“US”,父類的citizenship值為“Chinese”。

(2).第4條語句為:sTest.testModifierPublic();

     輸出結果為第2行:Student:Public

     第12行語句為:pTest.testModifierPublic();

     輸出結果為第18行:Student:Public

sTest、pTest都調用了方法testModifierPublic(),子類重寫了父類的此方法,當sTest調用時,很顯然要調用子類重寫後的方法;pTest調用時,由於該方法已被子類的方法覆蓋,所以調用的也是子類重寫後的方法。

(3).第5、6條語句分別為:

     System.out.println(sTest.name);

     System.out.println(sTest.getName());

     輸出結果為第3、4、5行:

     ha

     Student:getName()

     ha

     第13、14條語句分別為:

     System.out.println(pTest.name);

     System.out.println(pTest.getName());

     輸出結果為第19、20、21行:

     null
     Student:getName()
     ha

sTest.name是直接存取成員變數name,sTest.getName()是通過調用getName()方法間接獲得name的值;兩種方式都輸出了“ha”;雖然name隱藏了父類的name,getName()重寫了父類的getName(),但調用者是sTest,所以使用的都是子類的變數和方法;

name雖然被隱藏,但pTest是父類對象引用,所以訪問是是父類的name,所以輸出為NULL;但父類的getName()被覆蓋,所以調用的是子類的方法。

(4).第7、8條語句分別為:

     System.out.println(sTest.citizenship);

     sTest.staMethodHide();

     輸出結果為第6、7行:

     US

     Student:static Method

 

     第15、16條語句分別為:

     System.out.println(pTest.citizenship);

     pTest.staMethodHide();

     輸出結果為第22、23行:

     Chinese
     Person:static Method

對靜態成員變數和靜態方法而言,被隱藏時,由子類對象引用訪問或調用時,訪問或調用到的就是子類的變數或方法;由父類對象引用訪問或調用時,訪問或調用到的就是父類的變數或方法。

(5).第9條語句為:sTest.testSuper();

     輸出結果為:

     Super:

     Person:Public

sTest調用子類成員方法testSuper(),方法體中用到了super.testModifierPublic();,用super來顯式調用父類的方法,所以輸出的是Person:Public。

(6).第10條語句為:sTest.informationPrint();

     輸出結果為第10到16行:

     Student:getName()

     My name is(getName) ha

     My name is(name) null

     I am 0 years old

     Something is wrong!

     My hobby is null

     I am a chinese

<1>.子類沒有重寫父類的informationPrint()這個成員方法;

<2>.輸出的第10、11行,通過getName()方法得到的name值是“ha”,輸出的第12行,通過直接存取name得到的值為NULL;

       說明調用的是子類getName(),但訪問的父類的name;

       也就是說,子類調用父類未重寫的成員方法時,成員方法體中如果調用到某個方法被子類重寫了,則實際調用子類重寫後的方法;

       如果訪問到某個被隱藏的成員變數,則實際訪問到的是父類的成員變數。

<3>.輸出的第16行,可以看出訪問的靜態成員變數也是父類的變數。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.