创建对象只是开辟个堆内存那么简单吗?

java对象

对象的创建

java的对象是在运行时创建的,创建对象的的触发条件有以下几种:

  1. 用new语句创建对象,这是最常用的创建对象方法。
  2. 运用反射手段,调用java.lang.reflect.Constructor类的newInstance()实例方法。
  3. 调用对象的clone()方法。
  4. 运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法。

对象创建过程

java对象在创建时需要在方法区的运行时常量池去查找该类的符号引用,如果没有发现符号引用,说明该类还没有被JVM加载,所以要先进行JVM的加载。当JVM加载完时,会在java堆中分配内存。分配内存时会根据堆内存是否规整来分别进行两种方式的分配。
1.指针碰撞
把内存分为可用的和已用的,在中间放置一个指针,如果要分配对象的空间,则把内存的指针向可用的一端移动当前需要分配对象大小的距离。
2.空闲列表
当内存并不是很规整时,需要一个列表来维护那些列表是可用的,那些是不可用的。

当内存分配完成后需要对分配到内存空间的对象赋予零值(静态字段在类加载中就已经有值,所以不需要赋零值),接下来需要设置对象头的信息:如设置该对象的哈希码,属于哪个类,GC分代年龄等信息。从虚拟机的角度来看至此一个对象就创建完成,但是在java程序的角度看,对象的创建才刚刚开始,因为对象的值还没有设定,对象值得设定是由对象初始化化来完成的,初始化就是调用构造方法过程。

对象的初始化

当对象创建完成后,接下来就是进行对象的初始化了,也就是去执行构造方法。

父类的初始化

当子类对象创建之前首先会调用父类的构造函数,也就是会初始化父类,但是父类并没有被创建,也就是并没有在堆中给父类分配新的存储空间,而只是对父类的变量进行了赋值。从而达到子类可以使用父类的属性和方法的目的。

静态类的初始化

当一个类中有static修饰的方法或者是变量的话,那么当这个静态方法被第一次调用的时候,那么这个类就会初始化,就会调用此类的类构造器(在类加载过程中被JVM自动加入),类构造器只初始化一次,触发条件为实例构造器执行,或者是静态任何一个静态成员被引用,也就是说这个类只会初始化一次。

普通类的初始化

区别与父类和静态类的初始化,普通类的初始化是建立在对象创建之上的,也就是对象创建完成后会自动的去调用构造方法进行初始化。

对象创建及初始化实例

看完上面文字上的简单说明总感觉少些什么东西?就像一碗牛肉拉面没有卤鸡蛋一样。所以笔者要通过一个java代码来将上面的知识点串起来,让你有一个更清晰的认识。


public class Parent {
    int a = 1;
    static int b = 2;

    // 静态代码块
    static {
        System.out.println("执行Parent静态代码块:b =" + b);
        b++;
    }

    // 普通代码块
    {
        System.out.println("执行Parent普通代码块: a =" + a);
        System.out.println("执行Parent普通代码块: b =" + b);
        b++;
        a++;
    }

    // 无参构造函数
    Parent() {
        System.out.println("执行Parent无参构造函数: a =" + a);
        System.out.println("执行Parent无参构造函数: b =" + b);
    }

    // 有参构造函数
    Parent(int a) {
        System.out.println("执行Parent有参构造函数: a =" + a);
        System.out.println("执行Parent有参构造函数: b =" + b);
    }

    // 方法
    void fun() {
        System.out.println("执行Parent的fun方法");
    }

}

public class Child extends Parent {
    int c = 1;
    static int d = 2;
    // 静态代码块
    static {
        System.out.println("执行Child静态代码块:d =" + d);
        d++;
    }
    // 普通代码块
    {
        System.out.println("执行Child代码块: c =" + c);
        System.out.println("执行Child代码块: d =" + d);
        c++;
        d++;
    }

    // 构造函数
    Child() {
        System.out.println("执行Child构造函数: c =" + c);
        System.out.println("执行Child构造函数: d =" + d);
    }

    // 方法
    void fun() {
        System.out.println("执行Child的fun方法");
    }

}

public class Test {
    public static void main(String[] args) {
        Child demo = new Child();
        demo.fun();
        System.out.println("…………………………………………………………………………………………………………………………");
        Child child = new Child();
        child.fun();
    }
}

上面有三个很简单的类,一个Parent,一个Child,一个Test。当执行Test的main方法是会输出什么呢?

//输出结果
执行Parent静态代码块:b =2
执行Child静态代码块:d =2
执行Parent普通代码块: a =1
执行Parent普通代码块: b =3
执行Parent无参构造函数: a =2
执行Parent无参构造函数: b =4
执行Child代码块: c =1
执行Child代码块: d =3
执行Child构造函数: c =2
执行Child构造函数: d =4
执行Child的fun方法
…………………………………………………………………………………………………………………………
执行Parent普通代码块: a =1
执行Parent普通代码块: b =4
执行Parent无参构造函数: a =2
执行Parent无参构造函数: b =5
执行Child代码块: c =1
执行Child代码块: d =4
执行Child构造函数: c =2
执行Child构造函数: d =5
执行Child的fun方法

下面我们一起来看看这些输出是这么一步步产生的。





注:本文的重点不是虚拟机有关的详细执行,之后会专门写一个关于虚拟机加载的文章,所以有关细节问题都一笔带过了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,293评论 18 399
  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 6,937评论 0 62
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,014评论 11 349
  • 作为一名即将毕业、面临社会的大学生,我常常对自己的未来感到迷茫,之前总是认为毕业会很遥远,自己年纪还小,还可以挥霍...
    yewook阅读 977评论 1 21
  • 版权申明 本文是林炎小宝原创,转载请联系 再过2天, 传说中的1月9日就要到来, 那一天,微信小程序即将正式发布,...
    林炎小宝阅读 601评论 4 11