weixin_42298191 2008-11-14 00:42
浏览 448
已采纳

java类实现继承时,内存中父类和子类是怎样分配的?

我觉得java的一些特性与对象在内存中的分配方式是密切相关的。
比如说:Java的多态,正是因为new出的对象是在堆中分配的,而这种内存分配方式在编译期无需知道此对象所需要的空间和生存周期。

现在我很困惑的是,java类实现继承时,内存中父类和子类是怎样分配的?或者说有着怎样的联系呢。

例如:
父类:Father
[code="java"]
public class Father {
protected String classname = "Father";

public Father(){
}

public Father(String cn){
    setClassName(cn);
}
protected String getClassName(){
    return classname;
}

protected void setClassName(String cn){
    classname = cn;
}

}
[/code]

子类:Child
[code="java"]
public class Child extends Father{

public Child(){
}

public Child(String cn){
    super(cn);
}

private String cname = "Child";

public String getCname() {
    return cname;
}

public void setCname(String cname) {
    this.cname = cname;
}

}[/code]

此时,我写测试代码:
[code="java"]
public class FatherChildTest {
public static void main(String args[]){
System.out.println(new Child().getClassName());
System.out.println(new Child("be changed in constructor!").getClassName());
}
}
[/code]

输出内容很明显:
Father
be changed in constructor!

想问的是,测试代码中,[code="java"]new Child().getClassName()[/code]动作时,
我创建的是Child对象,而它有父类的方法,且可以返回父类中定义的变量。
那Child继承Father,是不是相当于JVM加载类时,保存的类信息中不仅仅是Child的信息,还包括Father的那些对子类可见的信息?
比如,其实JVM加载类Child时,保存的类信息其实是这样的一个类的信息:
[code="java"]
public class Child{

public Child(){
}

public Child(String cn){
    setClassName(cn);
}

private String cname = "Child";

//-------------来自父类 begin----------------
protected String classname = "Father";

protected String getClassName(){
    return classname;
}

protected void setClassName(String cn){
    classname = cn;
}
//-------------来自父类 End----------------

public String getCname() {
    return cname;
}

public void setCname(String cname) {
    this.cname = cname;
}

}
[/code]
此类留有父类对子类可见的信息。

还是说,有另外一种方式,可以把子类与父类联系起来。

请指点!

我想知道原理,但可能表达的不太清楚,见谅!

[b]问题补充:[/b]
我觉得java的一些特性与对象在内存中的分配方式是密切相关的。
比如说:Java的多态,正是因为new出的对象是在堆中分配的,而这种内存分配方式在编译期无需知道此对象所需要的空间和生存周期。

现在我很困惑的是,java类实现继承时,内存中父类和子类是怎样分配的?或者说有着怎样的联系呢。

例如:
父类:Father

public class Father {
    protected String classname = "Father";
    
    public Father(){
    }
    
    public Father(String cn){
        setClassName(cn);
    }
    protected String getClassName(){
        return classname;
    }
    
    protected void setClassName(String cn){
        classname = cn;
    }
}

子类:Child

public class Child extends Father{

    public Child(){
    }
    
    public Child(String cn){
        super(cn);
    }
    
    private String cname = "Child";
    
    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }
}
此时,我写测试代码:
public class FatherChildTest {
    public static void main(String args[]){
        System.out.println(new Child().getClassName());
        System.out.println(new Child("be changed in constructor!").getClassName());
    }
}

输出内容很明显:
Father
be changed in constructor!

想问的是,测试代码中,

new Child().getClassName()
动作时,
我创建的是Child对象,而它有父类的方法,且可以返回父类中定义的变量。
那Child继承Father,是不是相当于JVM加载类时,保存的类信息中不仅仅是Child的信息,还包括Father的那些对子类可见的信息?
比如,其实JVM加载类Child时,保存的类信息其实是这样的一个类的信息:
public class Child{
    
    public Child(){
    }
    
    public Child(String cn){
        setClassName(cn);
    }
    
    private String cname = "Child";
    
    //-------------来自父类 begin----------------
    protected String classname = "Father";
    
    protected String getClassName(){
        return classname;
    }
    
    protected void setClassName(String cn){
        classname = cn;
    }
    //-------------来自父类 End----------------
    
    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }
}

此类留有父类对子类可见的信息。

还是说,有另外一种方式,可以把子类与父类联系起来。

请指点!

我想知道原理,但可能表达的不太清楚,见谅!

-------------------补充------------------

以下是mccxj所说,我没太懂:

【子类里有一个区域放的父类的实例,子类内存区里有一个this指针,指向了这个内存区里包括的父类实例区,当把引用付给父类时,是把子类内存区里面的父类实例区域的引用给了父类的实例.】

子类内存区里this指针不是指向它自己的吗?
而super指针才是指向了父类的实例?
后面那句 【当把引用付给父类时,是把子类内存区里面的父类实例区域的引用给了父类的实例.】,同样不太懂,感觉很模糊。
是不是说,当把引用付给父类时,这个引用体现的其实是子类中父类实例的属性?
[b]问题补充:[/b]
我觉得java的一些特性与对象在内存中的分配方式是密切相关的。
比如说:Java的多态,正是因为new出的对象是在堆中分配的,而这种内存分配方式在编译期无需知道此对象所需要的空间和生存周期。

现在我很困惑的是,java类实现继承时,内存中父类和子类是怎样分配的?或者说有着怎样的联系呢。

例如:
父类:Father

public class Father {
    protected String classname = "Father";
    
    public Father(){
    }
    
    public Father(String cn){
        setClassName(cn);
    }
    protected String getClassName(){
        return classname;
    }
    
    protected void setClassName(String cn){
        classname = cn;
    }
}

子类:Child

public class Child extends Father{

    public Child(){
    }
    
    public Child(String cn){
        super(cn);
    }
    
    private String cname = "Child";
    
    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }
}
此时,我写测试代码:
public class FatherChildTest {
    public static void main(String args[]){
        System.out.println(new Child().getClassName());
        System.out.println(new Child("be changed in constructor!").getClassName());
    }
}

输出内容很明显:
Father
be changed in constructor!

想问的是,测试代码中,

new Child().getClassName()
动作时,
我创建的是Child对象,而它有父类的方法,且可以返回父类中定义的变量。
那Child继承Father,是不是相当于JVM加载类时,保存的类信息中不仅仅是Child的信息,还包括Father的那些对子类可见的信息?
比如,其实JVM加载类Child时,保存的类信息其实是这样的一个类的信息:
public class Child{
    
    public Child(){
    }
    
    public Child(String cn){
        setClassName(cn);
    }
    
    private String cname = "Child";
    
    //-------------来自父类 begin----------------
    protected String classname = "Father";
    
    protected String getClassName(){
        return classname;
    }
    
    protected void setClassName(String cn){
        classname = cn;
    }
    //-------------来自父类 End----------------
    
    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }
}

此类留有父类对子类可见的信息。

还是说,有另外一种方式,可以把子类与父类联系起来。

请指点!

我想知道原理,但可能表达的不太清楚,见谅!

问题补充:
我觉得java的一些特性与对象在内存中的分配方式是密切相关的。
比如说:Java的多态,正是因为new出的对象是在堆中分配的,而这种内存分配方式在编译期无需知道此对象所需要的空间和生存周期。

现在我很困惑的是,java类实现继承时,内存中父类和子类是怎样分配的?或者说有着怎样的联系呢。

例如:
父类:Father
<pre name="code" class="java">
public class Father {
protected String classname = "Father";

public Father(){
}

public Father(String cn){
    setClassName(cn);
}
protected String getClassName(){
    return classname;
}

protected void setClassName(String cn){
    classname = cn;
}

}
</pre>

子类:Child
<pre name="code" class="java">
public class Child extends Father{

public Child(){
}

public Child(String cn){
    super(cn);
}

private String cname = "Child";

public String getCname() {
    return cname;
}

public void setCname(String cname) {
    this.cname = cname;
}

}</pre>

此时,我写测试代码:
<pre name="code" class="java">
public class FatherChildTest {
public static void main(String args[]){
System.out.println(new Child().getClassName());
System.out.println(new Child("be changed in constructor!").getClassName());
}
}
</pre>

输出内容很明显:
Father
be changed in constructor!

想问的是,测试代码中,<pre name="code" class="java">new Child().getClassName()</pre>动作时,
我创建的是Child对象,而它有父类的方法,且可以返回父类中定义的变量。
那Child继承Father,是不是相当于JVM加载类时,保存的类信息中不仅仅是Child的信息,还包括Father的那些对子类可见的信息?
比如,其实JVM加载类Child时,保存的类信息其实是这样的一个类的信息:
<pre name="code" class="java">
public class Child{

public Child(){
}

public Child(String cn){
    setClassName(cn);
}

private String cname = "Child";

//-------------来自父类 begin----------------
protected String classname = "Father";

protected String getClassName(){
    return classname;
}

protected void setClassName(String cn){
    classname = cn;
}
//-------------来自父类 End----------------

public String getCname() {
    return cname;
}

public void setCname(String cname) {
    this.cname = cname;
}

}
</pre>
此类留有父类对子类可见的信息。

还是说,有另外一种方式,可以把子类与父类联系起来。

请指点!

我想知道原理,但可能表达的不太清楚,见谅!

-------------------补充------------------

以下是mccxj所说,我没太懂:

【子类里有一个区域放的父类的实例,子类内存区里有一个this指针,指向了这个内存区里包括的父类实例区,当把引用付给父类时,是把子类内存区里面的父类实例区域的引用给了父类的实例.】

子类内存区里this指针不是指向它自己的吗?
而super指针才是指向了父类的实例?
后面那句 【当把引用付给父类时,是把子类内存区里面的父类实例区域的引用给了父类的实例.】,同样不太懂,感觉很模糊。
是不是说,当把引用付给父类时,这个引用体现的其实是子类中父类实例的属性?

-------------------------再补充--------------------------
一下为bohemia 所说:
【super相当于指向父类示例的一个指针; 子类只保存子类的信息和super指针; 具体调用,先查找当前子类,然后查找父类是否有实现; 】

既然先查找子类,为何变量会找到父类呢?
(我查了,跟java的编译期绑定和运行时绑定有关)
想听听大家的理解。

[b]问题补充:[/b]
-------------------补充------------------

以下是mccxj所说,我没太懂:

【子类里有一个区域放的父类的实例,子类内存区里有一个this指针,指向了这个内存区里包括的父类实例区,当把引用付给父类时,是把子类内存区里面的父类实例区域的引用给了父类的实例.】

子类内存区里this指针不是指向它自己的吗?
而super指针才是指向了父类的实例?
后面那句 【当把引用付给父类时,是把子类内存区里面的父类实例区域的引用给了父类的实例.】,同样不太懂,感觉很模糊。
是不是说,当把引用付给父类时,这个引用体现的其实是子类中父类实例的属性?

-------------------------再补充--------------------------
一下为bohemia 所说:
【super相当于指向父类示例的一个指针; 子类只保存子类的信息和super指针; 具体调用,先查找当前子类,然后查找父类是否有实现; 】

既然先查找子类,为何变量会找到父类呢?
(我查了,跟java的编译期绑定和运行时绑定有关)
想听听大家的理解。

  • 写回答

6条回答 默认 最新

  • 「已注销」 2008-11-14 07:37
    关注

    子类里有一个区域放的父类的实例,子类内存区里有一个this指针,指向了这个内存区里包括的父类实例区,当把引用付给父类时,是把子类内存区里面的父类实例区域的引用给了父类的实例.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

悬赏问题

  • ¥15 高德地图点聚合中Marker的位置无法实时更新
  • ¥15 DIFY API Endpoint 问题。
  • ¥20 sub地址DHCP问题
  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办