java父类引用子类_Java学习笔记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类的代码为:

packagehuman;public classPerson {

String name;intage;

String gender;publicString education;privateString hobby;protectedString residence;static String citizenship = "Chinese";publicPerson() {

}public voidsetName(String n) {this.name =n;

}publicString getName() {returnname;

}public voidinformationPrint() {

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");elseSystem.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");elseSystem.out.println("Oh,something is wrong");

}//test:覆盖

public voidtestModifierPublic() {

System.out.println("Person:Public");

}//test:隐藏

public static voidstaMethodHide() {

System.out.println("Person:static Method");

}

}

Student类的代码为:

packagehuman;public class Student extendsPerson {

String stuNumber;intscore;//test:隐藏

String name = "ha";static String citizenship = "US";publicStudent() {

}publicStudent(String n, String g) {super(n,g);

}//test:隐藏

public voidsetName(String n) {this.name =n;

}//test:隐藏

publicString getName() {returnname;

}//test:覆盖

public voidtestModifierPublic() {

System.out.println("Student:Public");

}//test:super

public voidtestSuper() {

System.out.println("Super:");super.testModifierPublic();

}//test:隐藏

public static voidstaMethodHide() {

System.out.println("Student:static Method");

}

}

TestMain类的代码为:

packagehuman;public classTestMain {public static voidmain(String[] args) {

Student sTest= newStudent();

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();

}

}

输出结果为:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 下面是以子类对象sTest来访问变量、调用方法的结果:2 Student:Public3 ha4 Student:getName()5 ha6 US7 Student:staticMethod8 Super:9 Person:Public10 Student:getName()11 My name is(getName) ha12 My name is(name) null

13 I am 0years old14 Something is wrong!

15 My hobby is null

16 I am a chinese17 下面是以父类对象pTest来访问变量、调用方法的结果:18 Student:Public19 null

20 Student:getName()21 ha22 Chinese23 Person:static Method

View Code

下面对结果进行分析:

(1).前两条语句为:

Student sTest = new Student();

Person pTest = sTest;

第一条语句定义了子类对象引用sTest,并指向了一个子类对象;第二条语句定义了父类对象引用pTest,并被赋值为sTest的值;大体的内存结构见图1:

d1f9fd1fa33f75efa3e921c4a5445d95.png

图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行,可以看出访问的静态成员变量也是父类的变量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值