likes
comments
collection
share

《深入Java(五)》——对象的内存模型、实体与引用以及“垃圾收集”机制

作者站长头像
站长
· 阅读数 14

这是我参加“4月日新计划更文活动”的第七天

  • 在开始讲讲Java当中对象的内存模型之前,先摆出创建一个对象(也叫实例化对象)所必须经历的三个步骤。现在假设有一个Person类。:《深入Java(五)》——对象的内存模型、实体与引用以及“垃圾收集”机制

    • 1.首先给Person类当中的成员变量分配内存空间
    • 2.执行类中的构造方法
    • 3.计算出该对象独一无二的引用
  • 在本例中,系统首先要先给变量age,ID,work还有family分配对应数据类型的内存空间。接着使用类中合适的构造器对各变量进行初始化。在初始化构造器这一步呢,如果方法中没有具体为某个变量赋值,系统就会默认赋予“空类”(0、0.0、true、'\0'等等),最后计算出一个引用值,一个对象才算真正地被创建了。

  • 将刚才所说的引用值赋给引用变量victor,,victor可以通过存储起来的引用值访问对象当中的各个属性和方法。《深入Java(五)》——对象的内存模型、实体与引用以及“垃圾收集”机制

  • 知道了以上内容,我们可以用相同的方式,创建多个不同的对象。返回的引用值,和c一样,都是一个十六进制数。但每一个引用值绝对不一样,因此每一个引用变量(victor jenny)所指向的内存空间也都是互不相同的。《深入Java(五)》——对象的内存模型、实体与引用以及“垃圾收集”机制

  • 这里另外补充一个知识点:

    • 对象的引用存在内存的栈区,而对象的实体(即实例化得到的对象,所具有的属性/变量)存放在内存的堆区。有关栈和堆的知识,现阶段只需要知道,栈区空间较小,但存取速度比较快,而且分配给变量的内存有着相应的“生存期”(也就是C中“块”或者“本地变量”的概念),在同一个程序当中,这一块定义的变量,在另一块使用就是非法的了,因为变量空间已经被Java自动释放掉了。《深入Java(五)》——对象的内存模型、实体与引用以及“垃圾收集”机制
    • 而堆,可以动态分配内存大小,空间也比栈大得多,但是存取速度比较慢,灵活性也没有栈好。
    • 这样看来,小小的引用变量放在栈区,数据量通常比较庞大的对象成员变量就放在堆区,的确是比较合适。
  • 在很多时候,我们把已经实例化的对象称之为实体,默认的情况下,每一个实体都有一个独属于自己的引用。

  • 但这只是默认的情况对不对?引用真的不可以相同吗?

  • 要回答这个问题,我们首先要知道所谓的“类”,本质上就是一个封装了属性和方法的数据类型,指向实体的引用变量实质上也是变量。变量实质是什么?是一个容器,存放各类数据。容器之间当然需要赋值操作了。

  • 引用当然也可以,所以下面的语句是合法的。《深入Java(五)》——对象的内存模型、实体与引用以及“垃圾收集”机制

  • 这样一来,两个引用存放的引用值就是一样的了。指向的实体,自然也是一样的了。在本例中,这样就相当于,victor有了一个别名,叫bierce。

  • 但是这样就有了一个疑问,原本bierce的实体去哪里了?指向bierce实体的引用值已经被覆盖了,我们再也无法访问到原来的bierce了吗?

  • 是的,在面向对象编程当中,我们可以这样认为。但是我们还要再深入想想,既然已经找不到原来的实体了,他难道还占据着内存空间吗?为一个已经没有任何用处的实体继续保存空间,会不会太没有意义了?

  • 的确,内存的资源是那么的宝贵,我们的确要在堆中,回收掉这部分已经不再被栈中任何对象所引用的实体内存。Java运行环境有“垃圾收集”机制,可以周期性地检测某个实体是否已经不再被任何对象所拥有,一旦发现这样的实体,就会自动释放实体占有的内存。因此Java不像C++,类中总是要有一个析构方法,要手动地去释放内存。

转载自:https://juejin.cn/post/7222602874630602809
评论
请登录