前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面向对象Java开发——对象的内存原理和内存图

面向对象Java开发——对象的内存原理和内存图

作者头像
丹牛Daniel
发布2022-11-18 10:04:31
7700
发布2022-11-18 10:04:31
举报

在使用Java开发时,面向对象是重点和难点,而要理解面向对象的问题,最重要的还是要搞清楚其在内存中的原理和内存图,本文记录了Java对象在内存中的情况,包括this,基本数据类型和引用数据类型以及局部变量和成员变量的原理。

目录

预备知识

一、一个对象的内存图

二、多个对象的内存图

注意

三、两个引用指向同一个对象内存图

四、this的内存原理

五、基本数据类型和引用数据类型的区别

六、局部变量和成员变量的区别


预备知识

JVM虚拟机在整个计算机中占用一块内存,并且在内存中分为五个部分来各司其职:

重点是栈、堆和方法区:

当程序运行一个类,其字节码文件就会加载到方法区进行存储,方法区原本是和堆空间在一起,而从JDK8开始,取消方法区,新增元空间。把原来方法区的多种功能进行拆分,有的功能放到了堆中,有的功能放到了元空间中。如今,加载字节码的功能归给元空间了。

 当运行一个类时,这个类的字节码文件就会加载到方法区中临时存储。当方法被调用就要进栈,执行完就要出栈,而new出来的东西都会在堆内存。

一、一个对象的内存图

创建一个对象,要经历以下7个步骤

  1. 加载class文件
  2. 申明局部变量
  3. 在堆内存中开辟一个空间
  4. 默认初始化
  5. 显示初始化
  6. 构造方法初始化
  7. 将堆内存中的地址值赋值给左边的局部变量

比如说运行代码student s = new student() ,图中所做的事是:在这里呢有一个很简单的student类,这个里面有两个属性,一个是name,一个是age,在这个里面还有一个study()的成员方法。我们在测试类当中需要创建对象,测试类的名字叫做test student,首先创建了它的对象,然后打印s,再用s调用其中的name跟age并进行打印,在对name跟age进行了赋值,赋完值之后再获取并打印,最后调用study()。

内存会做这几件事件事。

  • step1:先加载class文件,在方法区里面,会把student.class加载到其中临时存储,,它会有student这个类的所有信息,比如说所有的成员变量,成员方法。
  • step2:声明局部变量,就是在创建对象等号s的这个代码,栈内会开辟了一个空间,名字就叫做s,这个空间之后能存储student这个类对象的地址值。
  • step3:在堆内存当中去开辟了一个空间,也就是在创建对象等号右边new student(),那此时来看堆,只要有new,就是在堆里面去开辟了个小空间,而堆里面的这些空间是有地址值的,假设这块空间的地址值是001,它就会把student这个类里面所有的成员变量都拿过来拷贝一份,还会有所有成员方法的地址,存储方法的地址,为了以后用对象调方法的时候能找到对应的方法。
  • step4:看到图中堆内,name初始值为null,age初始值为0。
  • step5:比如如果是定义类的时候直接String name="xxx"; int age=23;便需要显示初始化,也就是如果有这一步,便会覆盖默认初始化的值
  • step6:构造方法初始化,看到在代码当中啊,小括号里面什么都没写,就表示现在调用的是空参构造,而空参构造里面也没有写代码,所以说构造方法初始化也可以忽略。但是如果用的是有参构造来创建对象,那么现在name和age就会有值了。
  • step7:把栈内存中分配的地址值001,赋值给栈内存中的局部变量s

因此之后如果调用方法println(s)就会打印储存的地址值,println(s.name,s.age)就打印地址值对应的空间内的值。再赋值也是把"阿强" 和 23赋值给堆内存中成员变量。如果调用成员方法s.study()就会由堆内存储存的地址值再找到方法区对应的方法,并加载进栈内存。

study()和main()执行完便会出栈,main()中的变量也会消失,而没有变量指向的堆内存空间也会被消失,也就是清除了。

二、多个对象的内存图

同理,如果要处理不止一个对象,那么也来举个例子,比如说有两个对象,只要出现new,就说明要创建一个对象,在堆空间内开辟块空间,创建几个就开辟几块,且相互独立。

首先类加载进方法区。同上一样创建第一个对象student s1=new student(),接着打印对象,对age和name进行赋值,赋完值之后获取name,age,再用第一个对象去调用study()。接着创建了第二个对象进行了一遍相同的操作。其实很简单,就是把刚刚的一个对象重复了两次而已。

内存中的步骤也是:

  1. 测试类的字节码文件要被加载到方法区当中,其main()方法也会临时存储
  2. 虚拟机要调用main()方法,所以main()进栈
  3. 执行第一行student s1=new student(),左边的s1声明空间,等号右边有new关键字就是在堆里面开辟了一个小空间,其内会有所有成员变量的值,所有的成员方法的地值引用。对于成员变量会有默认初始化,显示初始化,构造方法初始化,再会把一个空间的地址001赋值给了左边的S1,那么S1就可以通过001找到了右边的对象的这个空间
  4. name和age的默认初始值是null和0,方法中进行赋值为阿强和23
  5. 调用study()方法,则方法进栈,调用完后方法出栈
  6. 接着相同步骤创建s2

注意

第二次创建对象class文件是否还要再加载一次?答案是不需要,因为class文件已经加载过了。所以说我第二次在创建对象的时候,class文件就不需要再加载了,直接用就可以了。

在s2的study()也调用完出栈后,没有可执行的语句,所以main()方法出栈,变量s1和s2也没有了,所以堆空间内的也会销毁。

三、两个引用指向同一个对象内存图

还是使用与上面相同的例子,但在这次第二个对象并没有new出来,而是把stu1这个变量里面记录的东西赋值给了stu2。在内存当中是这样的,首先会去声明一个stu2的小空间,这个空间也能存储student这个类对象的地址值,那你说这个空间里面存的是stu1这个里面记录的001赋值给了stu2,stu2记录的其实也就是001,也能通过001也能找到堆内存的空间,相当于就是两个变量都指向了同一个对象。

之后运行stu1=null 和 stu2=null就会分别让两个变量变为空指针,无法再打印堆内存储的值了。

四、this的内存原理

比如method()中第一个打印方法,会触发就近原则,便会打印局部变量的age,但要想使用成员变量的age就应在前面加上this. 那么this在内存中的原理可以从下图中看到

堆内存创建了对象,把001这个地址值赋值给栈中左边的变量s,method()是被s调用的,所以说方法里面记录的调用者的地址值就是001,那么this记录的也是001,这就是this的本质,它就是代表方法调用者的地址值。当前的方法是s调用的,s和this代表的都是地址值001。

五、基本数据类型和引用数据类型的区别

基本数据类型

  • 整数类型
  • 浮点数类型
  • 布尔类型
  • 字符类型

引用数据类型:除了上边的其他所有类型。

它们的本质区别在于:基本数据类型就是在内存空间储存真实的数据值,真实的存在栈中而与其他的空间没有关系。

而在代码中创建的对象都是引用数据类型,栈中存储的只是一个地址值,而对象真实的值是存储在堆内存中的。因此引用就可以理解为使用其他空间中存储的值。同理数组也是,栈内存储数组的地址值,真实值则是在堆内存中存储。

六、局部变量和成员变量的区别

成员变量:类中方法外的变量

局部变量:方法中的变量

 具体区别如下表

在内存当中,可以看到变量a在栈内的方法中,而name、age都是在堆内存为对象开辟的空间中。方法出栈,变量a自然也就销毁。而没有方法出栈,对象不再被调用,自然堆内存中存储的name和age也就都被销毁了。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-10-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 预备知识
  • 一、一个对象的内存图
  • 二、多个对象的内存图
    • 注意
    • 三、两个引用指向同一个对象内存图
    • 四、this的内存原理
    • 五、基本数据类型和引用数据类型的区别
    • 六、局部变量和成员变量的区别
    相关产品与服务
    对象存储
    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档