Java实例化(new)的本质

1:在方法区中寻找类定义 ,找到生成一个对象

 jvm会在自己的一个名叫“方法区”的内存块中,寻找名叫“MyObject”的Class对象(注意class也是一个对象,该对象记录了所有类的定义),如果有,则按照Class对象的定义,生成一个MyObject对象。 


 2:若方法区没有类定义,则加载类定义到方法区

如果“方法区”中没有名为“MyObject”的Class对象,jvm会用当前类的类加载器(classloader)从当前的classpath路径寻找名为"MyObject.class"的文件,如果找到,则将文件进行分析,转换为Class对象存放在“方法区”中,否则抛出“ClassNotFoundException”。对于jdk的class,jvm启动时,会用启动类加载器加载,对于用户的class,则会用应用程序类加载器实时加载,所谓实时加载,指的是遇到的时候再加载,而不是预先一次性加载。关于类加载器,有三级,jvm严格的限制了每一级的加载权限,加载模式为“双亲委托模式”,加载任何类,都先由父加载器加载。 


3:在堆中给对象分配内存空间 ,并设置默认值

 找到MyObject的类定义后,jvm在内存“堆”中,开辟一个空间,该空间按照MyObject类定义开辟,并将该空间中的各个内存段设置默认值,对应的就是对象的属性初始化默认值。 


4:对象的初始化顺序 (父类>当前类;静态>非静态;变量>构造方法)(变量与块是一个级别,根据位置来定先后
 对象的初始化都先从父类开始,顺序如下: 
 给父类静态变量默认值 
 对父类静态变量赋值 
 执行父类静态块 


 给当前类静态变量默认值 
 对当前类静态变量赋值 
 执行当前类静态块 


 给父类变量默认值 
 对父类变量赋值 
 执行父类构造函数 


 给当前类变量默认值 

 对当前类变量赋值 

 执行当前类构造函数


public class TestClassLoad {
    private TestClassLoad(){
        System.out.println("构造方法");
    }
    {
        System.out.println("11111");
//        System.out.println(str); //这个地方直接编译报错

    }
    private String str = "20";


    {
        System.out.println(str);
        System.out.println("2222");

    }
    public static void main(String[] args) {
        TestClassLoad testClassLoad = new TestClassLoad();
    }

}

输出结果:

11111

20
2222

构造方法


5:对象构造完成 


注:当new一个String的时候,只是生成一个String对象,而没有生成Object对象,Object的类定义在“方法区”这块内存中,当new String的时候,jvm会检查String的父类,找出父类的定义,并找出哪些是String可以拥有的,然后按照筛选出来的父类定义和String本身的类定义,在堆中分配一个内存块(就是俗称的生成了一个对象),而没有专门为String的父类Object分配空间。 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值