java是一种面向对象的编程语言,那么了解创建对象时程序会怎么执行就变得尤为重要,下面我们就一起看看在我们使用new关键字创建对象时是怎么对属性初始化的:

下面是一个Person类,其中有成员变量age和静态变量name

public class Person {private int age;            //年龄public static String name = "abc";           //姓名public Person(int age) {this.age = age;}
}

编译后接着用javap命令对其反编译:

{public static java.lang.String name;descriptor: Ljava/lang/String;flags: ACC_PUBLIC, ACC_STATICpublic Person(int);descriptor: (I)Vflags: ACC_PUBLICCode:stack=2, locals=2, args_size=20: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: aload_05: iload_1                           //将int类型的变量(构造方法中传的age)推至栈顶6: putfield      #2                  //对age属性进行赋值9: returnLineNumberTable:line 9: 0line 10: 4line 11: 9static {};descriptor: ()Vflags: ACC_STATICCode:stack=1, locals=0, args_size=00: ldc           #3                  // 将"abc"从常量池推至栈顶2: putstatic     #4                  // 对name属性赋值5: returnLineNumberTable:line 7: 0
}

在这里我们可以发现,对于成员属性来说,是在构造方法中初始化的,对于static属性编译器会在static代码块中对其初始化(按static语句的声明顺序)。那么如果我们直接在成员属性上显示赋值而不在构造方法中初始化呢:
为了方便观察,我在构造方法里加入了一个输出语句。

public class Person {private int age = 13;            //年龄public static String name = "abc";           //姓名public Person() {System.out.println("构造方法");}
}

javap反编译后:

public Person();descriptor: ()Vflags: ACC_PUBLICCode:stack=2, locals=1, args_size=10: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: aload_05: bipush        13                  //将单字节的常量值(-128~127)推送至栈顶7: putfield      #2                  // Field age:I(对属性age赋值)------------------ 下面是关于输出语句的代码 ------------------10: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;13: ldc           #4                  // String 构造方法15: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V18: returnLineNumberTable:line 9: 0line 5: 4line 10: 10line 11: 18

可以看到,对于直接对成员属性显示赋值的情况,编译器会将它放到构造方法中代码的前面执行,比如上面的代码就把对age属性的赋值放在了输出语句的前面。

为了更直观的观察创建对象时,jvm对属性的赋值过程,我们在idea里debug一下:



到这里,整个对象的初始化就完成了。可以发现,当字节码文件被加载到jvm中后,类中static属性其实并没有马上被赋值,而是先有了其类型对应的默认值,成员属性在new关键字开辟内存空间后,也是先有了默认值,直到构造方法对其赋值。

那么对于static final修饰的变量也是如此吗?

总结:
在我们使用new关键字创建一个对象的时候。
1.jvm会先去加载这个对象的类的字节码文件,并把其中static的属性放到方法区保存,此时这些属性还是其类型对应的默认值,(static final的变量除外,jvm会直接对其赋值)。
2.紧接着jvm会对这些方法区中的static变量进行赋值。
3.在方法区中static属性赋值完成后,new关键字就会在堆中去申请一块空间用来存储对象,此时对象中的成员属性就正式在内存中存在了,但会被赋予其类型的默认值。
4.在new关键字在堆中开辟内存空间后,jvm就会去调用对象的构造方法,在构造方法中对成员属性开始赋值,当构造方法执行完毕,成员属性也随之完成了赋值。到这里,整个对象的创建过程就算结束了。

关于java中创建对象时属性的初始化过程相关推荐

  1. java在创建对象时必须_Java中5种创建对象的方式

    以下是一些在Java中创建对象的方法: 1. 使用new关键字 使用new关键字是创建对象的最基本方法.这是在java中创建对象的最常见方法.几乎99%的对象都是这样创建的.通过使用这个方法,我们可以 ...

  2. 绝,Java 中创建对象的 5 种方法!

    我们日常生活中会创建很多对象,但是这个对象和你理解的那么对象不一样,因为作者不是女娲,不能造人.作者只是程序员,他只能在 Java 中创建对象. 那么我问你一个问题,你知道 Java 中如何创建对象吗 ...

  3. 12月18日云栖精选夜读 | Java 中创建对象的 5 种方式!...

    作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如Spring去创建对象.然而这里有很多创建对象的方法,我们会在这篇文章中学到. Java中有5种创建对象的方式,下面给出它们的 ...

  4. Java中创建对象的几种方式

    Java中创建对象的几种方式 1.使用new创建对象,在堆上创建. 2.克隆 3.反序列化 4.反射创建对象 5.NIO中可以使用本地方法直接分配堆外内存. 转载于:https://www.cnblo ...

  5. Java中创建对象的四种方式

    为什么80%的码农都做不了架构师?>>>    Java中创建对象的四种方式 (1) 用new语句创建对象,这是最常见的创建对象的方法.    (2) 运用反射手段,调用java.l ...

  6. java中创建对象的方式有哪些,Java中创建对象的四种方式

    四种方式: http://wenku.baidu.com/link?url=mv6VbMd3d-aCkbGMhn6rbLwFbef7v60nRbyA-thP6Y7hqtjiv0K0_kdtfOWaUj ...

  7. java中创建对象的一般格式是什么_Java零基础快速入门|对象的创建和使用(下)...

    本篇文章主要内容:构造方法Constructor 空指针异常 当实例变量是一个引用 方法调用时参数的传递问题 难点解惑 构造方法Constructor 什么是构造方法?构造方法怎么定义?构造方法怎么调 ...

  8. Java中创建对象的六个步骤 细分后(new关键字)对象头详细介绍

    要看的懂对象的创建过程,首先你得有对Java虚拟机和Java基础以及JUC很是熟悉, 比如类的加载过程.CAS.多线程.JVM的GC等等 文章目录 一.创建对象的六个步骤: 二.对象头的内部结构 首先 ...

  9. java中的static属性详细介绍

    标题 java中static属性详细介绍 类的生命周期 代码块 静态代码块: 静态方法 静态属性和非静态属性的区别: 使用static的注意事项 继承关系中静态和非静态的关系 普通代码块和构造代码块区 ...

最新文章

  1. 洛谷精选 - 字符串合集
  2. 使用 Linux 系统调用的内核命令
  3. 使用BootStrap框架设置全局CSS样式
  4. elementui源码_Element UI 终于还是来啦
  5. [转载] 晓说——第8期:镖局——最后的江湖(下)
  6. 微软发布8月安全公告 包含13个补丁修补22个漏洞
  7. php jumppage加载网址,php 分页类 扩展代码
  8. 数据和云2020年度最受欢迎的Top10文章、专栏、文档、直播资源大放送(建议收藏)...
  9. Java集合性能分析-疯狂Java讲义
  10. 深度分析 Java 的枚举类型:枚举的线程安全性及序列化问题(转)
  11. 学习 Python,这 22 个包怎能不掌握?
  12. Android-SDK下载及安装配置教程
  13. php表决器代码,adder3 此源代码是基于Verilog语言的七人投票表决器 、2 个 联合开发网 - pudn.com...
  14. html好看英文字体,js显示漂亮的英文字体实例
  15. win7局域网共享设置_win7局域网共享,教你在智能电视上看win7系统电脑资源
  16. lucene 创建索引慢的问题
  17. MuMu模拟器进行adb操作
  18. 程序员工资的7个段位,你的工资在哪个Level?
  19. Mybatis遇到的报错集合
  20. android飞行棋小程序,C#飞行棋小程序设计代码

热门文章

  1. legacy引导gpt分区_传统Legacy引导和MBR硬盘格式无损更换UEFI和GPT的操作
  2. linux 的常用命令(持续更新.....)
  3. 在Linux上,使用time优雅的统计程序运行时间
  4. linux下phylip软件构建NJ树,进化树构建-NJ法lpar;megarpar;
  5. python语法报错原因_python萌新最常见5大错误
  6. 让弹幕飞一会儿——腾讯视频弹幕(39W+)爬取实战
  7. python 斗图图片爬虫
  8. 幸福指数报告 -- 数据可视化+聚类分析
  9. 北京精雕自定义机床模型仿真
  10. 华为mate30如何开启USB网络共享