当类A继承Java中的类B时,堆中会发生什么

当类A继承Java中的类B时,堆中会发生什么,java,inheritance,jvm,heap,instance,Java,Inheritance,Jvm,Heap,Instance,在Java中,假设我们有两个类A和B,这样B继承A A有三个私有字段和一个带三个参数的构造函数: public class A { private int a ; private int b ; private int c ; public A(int a, int b, int c) { this.a = a; this.b = b; this.c = c; } } 这是B类 public class B extends A { publi

在Java中,假设我们有两个类
A
B
,这样
B
继承
A
A
有三个私有字段和一个带三个参数的构造函数:

public class A {
private int a ;
private int b ;
private int c ;

 public A(int a, int b, int c) {
    this.a = a;
    this.b = b;
    this.c = c;
 }
}
这是B类

public class B extends A {        

  public B() {
    super(1,2,3);
 }
}

我们考虑下面的测试类< /P>

public class TestA {

        public static void main(String[] args) {
            A a = new A(1,2,3);
            B b = new B();        
        }
    }
问题是,当创建带有私有字段的类
A
并由类
B
继承时,堆中的有序进程是什么?当创建这两个类的实例时,堆中会发生什么?内存分配是如何发生的,类在计算机内存中是如何交互的


我们还知道子类不能继承其超类的私有字段,那么调用构造函数
B()
时会发生什么呢

类对象像其他对象一样加载到堆中。这个对象只是表示类

很好,您可以阅读整个文档,了解类加载器是如何工作的,您不会发现任何“类在堆中加载”的内容。。此外,你可以在互联网上做一些初步的搜索,以进一步澄清

B类
将完美编译

现在请按顺序提问:

当创建带有私有字段的类A并由类B继承时,堆中的有序进程是什么

您无法根据jvm如何管理它们的顺序来确定它们的顺序,私有成员不是继承的,而是存在于父对象(super)中的实例化对象中

换句话说,是的,子类的实例将具有父类的私有字段的副本。 但是,它们对子类不可见,因此访问它们的唯一方法是通过父类的方法

当创建这两个类的实例时,堆中会发生什么

通常,在创建
A
B

B b = new B();
  • A.class
    对象的引用(在创建
    A
    class实例之后)
  • B.class
    对象的引用(在创建
    B
    class实例之后)
  • 对象实例变量块
  • A
    实例变量块(仅A、b、c)
  • B
    实例变量块(本例中无)
  • 然而,JVM的每个实现都可以自由选择如何分配它们

    我们还知道子类不能继承其超类的私有字段,那么调用构造函数B()时会发生什么呢

    当您调用
    B()

    它将调用
    super(1,2,3)

    那之后会发生什么呢?没有传递给
    super()的值被传递到
    A(int A,int b,int c)
    ,然后分配给
    A
    的实例变量,但这并不意味着
    b
    现在可以访问这些私有字段。。您刚刚将值传递给了超级类构造函数,仅此而已

    --编辑--

    如果您想更好地理解堆和堆栈,请参阅

    --编辑-2--

    如果您花一点时间来研究这个问题,它已经掌握了JVM的一切,包括堆中的进程和其他内存结构

    --最终编辑-3--

    在OP关于超级阶级私人成员的评论中


    这个问题的答案将消除您对继承成员和不可访问的私有成员的混淆,因为子类实例是超级类的实例,它的实例具有父类的所有字段!该孩子看不到私人成员!!这就是您所指的JLS规范!它们占据了物体内部的空间。它们对子类不可见,但它们在该实例中

    类B将不会编译。@BetaRide它将编译compile@BetaRide我知道B类不会编译。我不是问它是否编译。我在问堆的级别发生了什么。我想在内存级别理解这些类之间的关系。虽然子类不会“继承”超类的私有字段,但这些字段仍然存在(并占用空间),并且当B的构造函数调用超类构造函数(无论是否隐式)时,这些字段将在某个点被初始化。B中的方法可以在同一实例上调用超类方法,并且必须能够访问超类中的私有字段。“不继承私有字段”只是意味着这些字段在B中的代码中是不可见的,但它们仍然存在。关于如何组织这些字段的许多细节都与实现高度相关。JLS规定了必须发生的事情,而不是如何发生。您从sharp edge接受的答案包含几个完全错误的东西&应该是不可接受的。例如,JLS没有提到类应该加载到哪里,而在Open/OracleJDK 7及以下版本(地球上最流行的JVM之一)中,类被加载到堆中,尽管在一个名为permgen的私有区域中,用户代码不能直接接触到它。我已经在询问这个过程所涉及的JVM。JVM的进程不是任意的。它是有组织的。JVM的进程顺序并不重要,因为它可以随JVM的不同实现而变化。。JVM的典型过程在我的第二个答案中:)非常感谢我的回答。但是问题已经是关于JVM的过程了。@Sharp edge先生,这里有一种困惑。您说私有字段由子类继承,并且只能由超类的构造函数访问。但根据调查,他们根本不是继承的。你能告诉我一个消息来源说私有字段是由sybclass继承的吗?@pentanol我从来没有说过私有成员