Java创建一个对象的过程是怎样的

目录

举个例子

对象创建过程

1.检测类是否被加载:

2.为对象分配内存:

3.为分配的内存空间初始化零值:

4.对对象进行其他设置:

5.执行 init 方法:

Java属性在类加载过程中的初始化顺序


举个例子

    class Fu {
        {
            System.out.println("这是父类的匿名代码块:父类的非静态属性");
        }
        static {
            System.out.println("这是父类的静态方法");
        }
        public Fu() {
            System.out.println("这是父类的构造方法");
        }
    }
    class Zi extends Fu {
        {
            System.out.println("这是子类的匿名:子类的非静态属性");
        }
        static {
            System.out.println("这是子类的静态方法");
        }
        public Zi() {
            //super();//一般都是省略的
            System.out.println("这是子类的构造方法");
        }
    }
    public class Main{
        public static void main(String[] args) throws ClassNotFoundException {
            Zi zi = new Zi();
     
        }
    }

 在main函数中new Zi() 会先去方法区的常量池中找有没有Zi这个类,发现没有,执行类的加载,链接,初始化。

Java类加载机制_trigger333的博客-CSDN博客_java类加载的机制

之后在使用这个类创建对象,具体如下。

对象创建过程

1.检测类是否被加载:

  当虚拟机执行到new时,会先去常量池中查找这个类的符号引用。如果能找到符号引用,说明此类已经被加载到方法区(方法区存储虚拟机已经加载的类的信息),可以继续执行;如果找不到符号引用,就会使用类加载器执行类的加载过程,类加载完成后继续执行。

2.为对象分配内存:

  类加载完成以后,虚拟机就开始为对象分配内存,此时所需内存的大小就已经确定了。只需要在堆上分配所需要的内存即可。

  具体的分配内存有两种情况:第一种情况是内存空间绝对规整,第二种情况是内存空间是不连续的

  • 于内存绝对规整的情况相对简单一些,虚拟机只需要在被占用的内存和可用空间之间移动指针即可,这种方式被称为指针碰撞。
  • 对于内存不规整的情况稍微复杂一点,这时候虚拟机需要维护一个列表,来记录哪些内存是可用的。分配内存的时候需要找到一个可用的内存空间,然后在列表上记录下已被分配,这种方式成为空闲列表

  分配内存的时候也需要考虑线程安全问题,有两种解决方案:

  • 第一种是采用同步的办法,使用CAS来保证操作的原子性
  • 一种是每个线程分配内存都在自己的空间内进行,即是每个线程都在堆中预先分配一小块内存,称为本地线程分配缓冲(TLAB),分配内存的时候再TLAB上分配,互不干扰。

3.为分配的内存空间初始化零值:

  对象的内存分配完成后,还需要将对象的内存空间都初始化为零值,这样能保证对象即使没有赋初值,也可以直接使用

4.对对象进行其他设置:

  分配完内存空间,初始化零值之后,虚拟机还需要对对象进行其他必要的设置,设置的地方都在对象头中,包括这个对象所属的类,类的元数据信息,对象的hashcode,GC分代年龄等信息。

5.执行 init 方法:

  执行完上面的步骤之后,在虚拟机里这个对象就算创建成功了,但是对于Java程序来说还需要执行init方法才算真正的创建完成,因为这个时候对象只是被初始化零值了,还没有真正的去根据程序中的代码分配初始值,调用了init方法之后,这个对象才真正能使用。

Java属性在类加载过程中的初始化顺序

静态优于非静态 > 父类优于子类

    class Fu {
        {
            System.out.println("这是父类的匿名代码块:父类的非静态属性");
        }
        static {
            System.out.println("这是父类的静态方法");
        }
        public Fu() {
            System.out.println("这是父类的构造方法");
        }
    }
    class Zi extends Fu {
        {
            System.out.println("这是子类的匿名:子类的非静态属性");
        }
        static {
            System.out.println("这是子类的静态方法");
        }
        public Zi() {
            //super();//一般都是省略的
            System.out.println("这是子类的构造方法");
        }
    }
    public class Main{
        public static void main(String[] args) throws ClassNotFoundException {
            Zi zi = new Zi();
     
        }
    }

    这是父类的静态方法
    这是子类的静态方法
    这是父类的匿名代码块:父类的非静态属性
    这是父类的构造方法
    这是子类的匿名:子类的非静态属性
    这是子类的构造方法


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

trigger333

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值