class Base{
private String name;
private double size;
public Base(double dax,String mz)
{
this.name=mz;
this.size=dax;
}
}
public class Sub extends Base{
public String color;
public Sub(double size,String name,String color)
{
super(size,name);
this.color=color;
}
public static void main(String[] args)
{
Sub s=new Sub(5.6,"
测试对象
","
红色
");
}
}
注意到
Base
中
name
和
size
都是
private
的,子类中不可能继承,那么子类中
super(size,name)
调用父类构造函数
改变的是哪个对象的什么变量的值呢?是子类的对象还是父类的对象?
是不是每当创建子对象时系统默认创建相应的父对象???
执行了
Sub s=new Sub(5.6,"
测试对象
","
红色
");
这句后,内存中有几个对象?属性值分别是什么?
讨论开始:
---------------------------------------------------------------------------------------------------------
(解答:)首先说明一点,对象只有一个,无论多少层的继承,都只有一个对象。
继承是相对于类而言,不想对于对象而言,类有继承的关系,对象是没有这个说法的。
private
会被子类所继承,不仅仅是
private
,如果子类有与父类同名的属性或者方法,同名的也会被继承,他们只是不能被访问,并不代表他们没有被继承下来。
问题补充:请问子类继承父类的属性和方法,则创建子类对象时不管是
private
的还是
public
的是否都在内存中实际存在呢?
解答:必须,否则你的对象还怎么能正常工作呢?要知道基类的所有方法,基本上都是建立在那些
private
属性和
private
方法上开展工作的。
之所以
private
,其实本质上是就是为了保护基类自己的运行环境不被随意调整,所以让你不可见。
解答:子类中不可能继承,这句话是错的。私有成员是不能在其他地方直接访问。子类继承父类的所有东西。当创建子类对象时,内存中会开辟一个父类的空间(并不是创建一个父类对象,也就是说从始至终只有一个对象),所以现在回答楼主问题。
问:改变的是哪个对象的什么变量的值呢?
答:
super
方法调用父类构造方法,改变子类实例
s
的
size
和
name
值。
问:是子类的对象还是父类的对象?
答:
s
是子类对象。所以改变的是子类对象。
问:是不是每当创建子对象时系统默认创建相应的父对象???
答:不是。
问:执行了
Sub s=new Sub(5.6,"
测试对象
","
红色
");
这句后,内存中有几个对象?属性值分别是什么?
答:一个。值的话,应该不用说了吧。。。
继续问:既然子类不能访问父类中
private
修饰的成员,那么继承过来的
private
成员有什么用
?
我
9
楼其实说了,我再换个方式解释下。
所继承过来的
private
成员,不是直接供子类使用的。而是供父类所提供方法来使用的。
比如你的父类如果是这样:
Java code
class Base{
private String name;
private double size;
public void setSize(double newSize) {
this.size = newSize;
}
}
那么如果你的子类没有完整继承
private
的
size
的话,那么子类的实例(对象)调用
setSize
方法时,
JVM
怎么办?所以必须要有基类完整的内容,基本是那些已经被子类重写的函数,也仍然会有。
下面引用《java 编程思想》的一段话:
由于这儿涉及到两个类――基础类及衍生类,而不再是以前的一个,所以在想象衍生类的结果对象时,可能会产生一些迷惑。从外部看,似乎新类拥有与基础类相同的接口,而且可包含一些额外的方法和字段。但继承并非仅仅简单地复制基础类的接口了事。 创建衍生类的一个对象时,它在其中包含了基础类的一个“子对象”。这个子对象就象我们根据基础类本身创建了它的一个对象。从外部看,基础类的子对象已封装到衍生类的对象里了。
当然,基础类子对象应该正确地初始化,而且只有一种方法能保证这一点:在构建器中执行初始化,通过调用基础类构建器,后者有足够的能力和权限来执行对基础类的初始化。在衍生类的构建器中,Java会自动插入对基础类构建器的调用。
从一开始,
Java
的语法结构就会把人往一个错误的方向去引领
(
或许这不是一种错误,因为
Java
本身是希望程序员去这么思考与应用,但是它是与实际执行是背离的
)
,
super
在语法层次,看上去就像父类对象的指针,但是事实却不是,在构造函数第一句的
super
指的是一个父类的构造方法,即使你不加
super
,那么虚拟机会自动添加
super()
在任何构造方法的第一句,也就是说父类构造方法一定会被执行。而普通方法中的
super.xxx
中的
super
也不是父类的对象,而是一个引用父类类型的一个指针,其实无论
super
还是
this
,把它理解为指向对象其实是并不太合适的。更好的理解应该是指向当前类型,因为无论怎么样,对象只有一个。
另外,方法与属性其实是有区别的,对象的成员属性是多个的,他会与对象一起存放在堆中,但是方法都是只有一个
(
至少在一个域中是如此,想要了解域,你要学习类的装载机制、类型管理与
jdk
安全机制,这个你可以自己去学习
)
,方法都只属于类,虽然很多时候动态看上去都属于某个对象,恰恰相反,是这个对象属于这个方法。因为静态方法与动态方法唯一的一个区别,就是一个不能用
this
一个能用
(
当然,调用的指令与
jvm
方法搜索机制都不同,但是这些不能决定他们的本质,关于这点你可以去查看
jvm
指令集说明
)
,动态方法只是有第一个默认参数,当前对象
this
,而静态方法没有这个缺省对象,我只介绍到这里,更深入的,你还是自己去看吧,如果你真的想要理解
java
底层,你就要完全跳出
java
的语法对你的影响,因为
jvm
是
C
语言开发的,他的字节码执行逻辑是类汇编,用面向对象去理解这些东西,会出现偏差那就是很正常的事情了。