美文网首页
JAVA继承中的初始化过程以及创建子类对象在内存中的分配

JAVA继承中的初始化过程以及创建子类对象在内存中的分配

作者: Mikasa___ | 来源:发表于2019-11-18 14:34 被阅读0次
public class Doctor {  
    public String name;    //成员变量
    public int age;
    //无参构造
    public Doctor() {           
      super();     //访问object类无参构造,一个类代码里没指定父类,默认继承Object类
    }
    //带参构造,也可看作是构造函数的重载
    public Doctor(String name, int age) {
      super();
      this.name = name;
      this.age = age;
    }
    public String getName() {
      return name;
    }
    public void setName(String name) {
      this.name = name;
    }
    public int getAge() {
      return age;
    }
    public void setAge(int age) {
      this.age = age;
    }
  
    public void talk(){
            int x = 8;      //此处举例x是局部变量,随着方法进栈,不会默认初始化,必须手动赋值
            ...
    }
  }

构造函数:创建对象时调用的函数,给对象初始化。成员变量默认初始化值如 int是0 String 是 null
代码里提供了两种构造函数,带参和不带参,那么创建Doctor类有两种方式(实际开发中可以根据需要创建构造函数和new对象)

Doctor d1 = new Doctor();
Doctor d2 = new Doctor("Tom",30);

相应的对成员变量赋值的话,第二种是创建对象时已经赋值了,第一种需要用到set方法,如 d1.setName("华佗") 此方法是没有返回值的,方法里面的this就是哪个对象调用这个方法,指的就是这个对象。相当于new Doctor().setName("华佗")传参“华佗”赋值给new出来的Doctor d1的成员变量name,值赋给它
比如以后的方法中需要用到name的值,可以通过get方法拿到String s = d1.getName();返回前面d1的成员变量name的值

ps成员变量与局部区别:
1、成员变量定义在类中,整个类中都可以访问;局部变量定义在函数、语句、局部代码块中,只在所属代码块中有效
2、成员变量存在于堆内存的对象中;局部变量存在于栈内存的方法中
3、成员变量随着对象的创建而存在,对象的消失而消失;局部变量随着所属区域的执行而存在,所属区域的结束而释放
4、成员变量有默认的初始化值;局部变量没有默认初始化值,必须赋值,否则编译报错

创建对象的实例化过程中在内存中的分配:

public static void main(String[]args){
    Doctor d1=new Doctor(“华佗”,30);   
    
}

1 程序运行时main函数先进栈,对变量Doctor d1在栈中开辟空间,是引用变量
2 JVM读取指定路径下的Doctor.class文件,类加载器将Doctor类信息加载进方法区(有父类会先加载父类)
在这个类的方法区,构造方法Doctor()有相应地址值
3 在堆中给对象开辟内存空间,分配地址值,
在该内存空间中对成员变量进行默认初始化,构造方法的引用标记,指向方法区的构造方法
4 调用构造函数,对新建的对象成员变量进行赋值“华佗” 30
5 初始化完毕后堆中地址值指向栈中的 d1
如果有直接父类,在第四步调用子类构造函数时会先调用父类构造函数进行初始化,父类初始化完毕后,子类再进行显示初始化

public class SuperTest {
    public static void main(String[]args) {
    Son s = new Son();
    }
    }

class Cat {
    Cat(String s){
        System.out.println(s);
    }
}

class Father{
    Cat c = new Cat("父亲的猫");
    public Father() {
        System.out.println("父类");
    }
}

class Son extends Father{
    Cat cc = new Cat("儿子的猫");
    public Son() {
        System.out.println("子类");
    }
}

构造函数以外可以是代码块,他们在一个类里面,每次创建这个类的对象,调用构造函数时,都会先执行代码块,无论代码块在构造函数的上面还是下面。

public class SuperTest {
    public static void main(String[]args) {
    Son s = new Son();
    }
    }

class Cat {
    Cat(){
        System.out.println("Cat");
    }
}

class Father{
    
    public Father() {
        System.out.println("父类");
    }
    {
    Cat c = new Cat();
    System.out.println("代码块在构造函数下面也会先执行");
    }
}

class Son extends Father{
    Cat cc = new Cat();
    public Son() {
        System.out.println("子类");
    }

}

一个类中如果没定义过构造函数,那么编译后系统会给一个默认的空参数构造函数。

public class SuperTest {
    public static void main(String[]args) {
    Son s = new Son();  
    }
    }

class Father{  //这里不写无参/带参构造函数,系统默认给无参构造函数
    
}

class Son extends Father{
    public Son() {
        //super(); 在这里写不写都可以,不写也会默认去调用父类无参构造函数
        System.out.println("子类无参访问父类无参");
    }
    public Son(String s) {
        super("子类带参访问父类带参"); //报错父类带参构造函数没有被定义过
        System.out.println("子类带参不再访问父类带参");
    }
}

如果一个类定义了有参构造函数,没定义过无参构造函数,后面new出来的对象想调用无参构造函数,如new 类名()会报错。

public class SuperTest {
    public static void main(String[]args) {
    Father f = new Father(); //比如创建对象无参,这里会报错the constructor father() is undefined  
    }
    }

class Father{
    public Father(String s) {
        System.out.println("父类带参构造");
    }
}

因为有了有参构造函数,编译后系统将不会再给默认的空参数构造函数。所以建议最好每次构造函数给出无参构造,无论有无带参构造函数,用到哪种可以调用哪种。也方便子类继承无参构造。

继承中的构造函数:
如果子类构造器没有显式地调用父类的构造器,则将自动调用父类的默认无参构造器。
如果父类没有无参构造器,有带参构造器,在子类的构造器中又没有显式地调用父类的带参构造器,则java编译器将报告错误。

public class SuperTest {
    public static void main(String[]args) {
    Son s = new Son();
    }
    }

class Father{
    public Father(String s) {
        System.out.println("父类带参构造");
    }
}

class Son extends Father{
    public Son() {
        super();   //这一行编译期会报错,父类无参构造函数没有被定义过
        System.out.println("子类无参访问父类带参");
    }
    public Son(String s) {
        super("子类带参访问父类带参");
        System.out.println("子类带参不再访问父类带参");
    }
}

父类只有带参构造,每个子类(带参或无参)第一行必须访问父类带参。不写的话默认调用父类空参,而父类空参没有创建,会报错。
可通过两种方式访问,第一种如下都是super(带参)

public class SuperTest {
    public static void main(String[]args) {
    Son s = new Son();
    }
    }

class Father{
    public Father(String s) {
        System.out.println("父类带参构造");
    }
}

class Son extends Father{
    public Son() {
        super("子类无参访问父类带参");
        System.out.println("子类无参访问父类带参");
    }
    public Son(String s) {
        super("子类带参访问父类带参");
        System.out.println("子类带参不再访问父类带参");
    }
}

第二种:一个子类A构造访问过了super(带参)另一个子类B通过this(...)调其他子类A去访问父类带参,this语句只能放在构造函数的第一行,因为初始化动作要先执行。

public class SuperTest {
    public static void main(String[]args) {
    Son s = new Son();
    }
    }

class Father{
    public Father(String s) {
        System.out.println("父类带参构造");
    }
}

class Son extends Father{
    public Son() {
        this("子类无参访问另一个我带参子类来访问父类带参");
        System.out.println("子类无参访问父类带参");
    }
    public Son(String s) {
        super("子类带参访问父类带参");
        System.out.println("子类带参不再访问父类带参");
    }
}

相关文章

  • Java对象创建与内存分布

    本文主要讲述Java对象在虚拟机中创建,分配内存,初始化的过程,以及分配内存,引用对象的几种常见方式。 对象创建 ...

  • JAVA继承中的初始化过程以及创建子类对象在内存中的分配

    构造函数:创建对象时调用的函数,给对象初始化。成员变量默认初始化值如 int是0 String 是 null代码里...

  • java对象的创建过程是什么

    java对象的创建过程是什么 java对象的创建过程: 类加载检查-->分配内存-->初始化零值-->设置对象头-...

  • java基础-day10-面向对象4.0

    面向对象4.0 1. 面向对象之继承 1.1 生活中的继承 1.2 Java中的继承 1.3 子类对象创建,会调...

  • JVM

    1.Java对象创建的过程? 类加载检查、分配内存、初始化零值、设置对象头、执行 方法。 2.JVM内存模型 / ...

  • 技术问 - 类的初始化过程

    类的初始化过程: 代码: 在内存中的执行过程: 类的初始化过程 创建对象并赋值在内存中的过程: 创建对象并赋值说明...

  • Java对象

    Java对象的内存布局?对象的访问?new对象的过程? 一、Java对象的内存布局 对象的创建过程就是在堆上分配实...

  • java中的私有变量是否可以继承

    java中的私有变量是否可以继承 Java 父类中权限为private的私有变量,子类对象继承后,在其内存中其实也...

  • J.U.C并发包之Executor与线程池

    在java创建对象的过程中,创建对象,是在 JVM 的堆里分配一块内存;而创建一个线程,需要调用操作系统内核的 A...

  • Java 对象创建过程。init 方法和 clinit方法。

    Java 对象创建过程 判断是否加载、分配内存(指针碰撞或者空闲链表)、初始化为零值、设置对象头(实例是哪个类的实...

网友评论

      本文标题:JAVA继承中的初始化过程以及创建子类对象在内存中的分配

      本文链接:https://www.haomeiwen.com/subject/diluictx.html