首页 > 编程语言 > 详细

java编程思想-多态 深入理解

时间:2016-01-10 02:04:39      阅读:172      评论:0      收藏:0      [点我收藏+]

先看两段代码:

publicclass D extends C{

public D(){

System.out.println("D-init");

}

?

publicstaticvoid main(String []args){

C c = new D();

System.out.println(c.getClass().getName());

c.f2();//编译出错,无法访问到f2()

}

}

?

class C {

public C(){

System.out.println("C-init");

}

?

privatevoid f2(){

System.out.println("C-private-2");

}

}

?

===========================================================

publicclass D {

public D(){

System.out.println("D-init");

}

?

privatevoid f2(){

System.out.println("D-private-2");

}

?

publicstaticvoid main(String []args){

D d = new C();

System.out.println(d.getClass().getName());

d.f2();

}

}

?

class C extends D{

public C(){

System.out.println("C-init");

}

?

publicvoid f1(){

System.out.println("C-public");

}

?

}

?

output:

D-init

C-init

com.keyword._static.C

?

D-private-2

?

首先我们知道子类的对象可以赋值给父类的引用,这是多态的一个体现。

但是为什么我们在D?d?=?new?C();之后,可以访问到父类的私有函数?

理论上来说,我们new 的是子类,也就是在堆区开辟的是子类的空间,而D d 只是一个引用,指向该子类对象在堆区地址。但是根据private私有的特性,我们认为是说到底这个子类的对象仍旧无法访问到父类中的private属性,哪怕编译时不报错,运行时也会出错。但是这里却正常的运行了,也成功访问到了父类的private属性,所以提出一个问题,这是怎么做到的?

?

解决这个问题也许不是来的那么直观。

其实现在假设new D()也就是创建一个父类对象,所需内存空间为1MB,那么在创建其子类对象new C();所需的内存空间必然大于1MB,先假设是1.5MB。

为何会多出一些空间,因为从构造链可以看出,初始化一个子类实例,必然会先初始化其父类实习,那么这个new 的父类实例放在哪里,其实放在子类的堆区内存中,也就是说,子类对象所在的内存空间,不但包含自己的信息,也有其父类的信息,而且是每个子类对象独立享有各自父类对象实例。

而D?d?=?new?C();这部操作,进行一个向上转型,也就是窄化操作,说白点就是一个本身指在子类对象范围以及父类非private对象范围的堆区可移动指针,重新使他只能指在父类对象范围内。

那么,这种条件下,是否能访问到private属性,我个人认为取决于运行的外部环境了,我觉得是堆栈环境,不知道这么说是否恰当。

?

在第二份示例代码中,main函数放在父类中,也就是说入口在父类,比如说当前运行的环境是父类环境,D?d?=?new?C();这部操作后,移动指针,指向父类的内容区间, 加上外部环境,我将其理解成,在父类环境中访问父类私有属性,也就是在自己家用自己的私有物品。那自然是可以访问的。

而第一份示例代码中,main函数放在子类中,也就是外部环境不是父类,那么哪怕堆栈指针移动到了父类的内容区间,也是无法访问到父类的private的,这是由private本身性质所决定的。

?

?

java编程思想-多态 深入理解

原文:http://870604904.iteye.com/blog/2269568

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!