本篇为记录不同的Java资料型态在记忆体中的变化情形,参考JVM 的 Stack 和 Heap并重点摘要。
Java语言中,资料型别分为基本型别
及参考(类别)型别
2种,特性如下:
byte
、short
、int
、long
、float
、double
、boolean
、char
特性
:
不属於基本型别的,都属於此类别,这种类型通常都需要用 new
去创建,如 User user = new User("Mark")
; 。
特性
:
储存函数路径
及区域变数
。变数a
的123
。函数路径
:Stack 内的变数值为物件实体在 Heap 中回传所在的记忆体位址,如上图的0x1234。後进先出
(FILO) 的容器,具有存取速度快
和管理简单的特点。下往上堆
,如图b在a上面。区域变数只能存在methods中
),所以由系统自行去产生和回收空间即可,不用特别设计垃圾回收机制。物件实体
的属性资料
,如图中的name :Mark
,并产生位址:0x1234
。记忆体位址
给stack
。没有立即给值
的情况下,也是要等new一个该类别的物件实体,才会在heap中建立该物件的值,并把预设值存放进去
,之後再把记忆体位址
给stack
。共享资料
,所以同 Process
底下的其他 Thread 也可以进行存取。Garbage Collection
机制,因为无法掌握物件实体的生命周期,所以存取速度慢
,但是GC是否有提升效能的部分还是有待讨论。两个物件实体:当a物件 = b物件,代表b物件在stack中只是把heap的位址
给a物件。
两个区域变数:a = b,代表区域变数b在stack中把区域变数a的值给覆盖
。
运作如下图
当在heap中没被参考到的物件,也就是没有变数储存他的位址
(如上图0x12),就由JVM的GC机制
回收并释放记忆体空间。
参数
使用基本型别跟类别型别的差异: static void passValue(double value) {
value = 20.0;
}
static void passReference(Pen reference) {
reference.price = 20.0;
}
public static void main(String[] args) {
double price = 10.0;
passValue(price);
System.out.println(price); // 10
Pen myPen = new Pen();
myPen.price = 10.0;
passReference(myPen);
System.out.println(myPen.price); // 20
}
解:
当资料为基本型别时:
price
值为10.0
的空间。passValue
调用该值成为该方法的参数
时,会在stack再建立一个空间储存该参数(value
)的值10.0
。value
被赋予新的值20.0
。passValue
运作结束,区域变数value
的生命周期也结束了。price
还是一样没有变化为10.0
。当资料为类别型别时:
price
值为10.0
的空间,并回传位址0x12
给stack并储存在变数myPen
。passReference
调用该值(位址0x12
)成为该方法的参数
时,会在stack再建立一个空间储存该参数(reference
)的值0x12
。reference
的属性price
值在heap
中会被更改为20.0
。passReference
运作结束,区域变数reference
的生命周期也结束了。myPen
因为属性price
的值在heap
中已经被更改为20.0
,所以最後print出来的值就变为20.0。参考资料:
JVM 的 Stack 和 Heap:https://blog.marklee.tw/java-interview-jvm-stack-heap/
<<: Jupyter Notebook 输入栏位设计(1)
>>: Java:观念厘清(新手用)-单元运算子a++与++a的差异
先检查一下你的专案结构是不是大概长成这样,有一些是後来才新增的功能。 假设原本我们安装的ngrok放...
DAY3 MongoDB 连线与 IDE MongoDB 的连线方式主要有三种,分别是: legac...
前情提要: 在上一集解释了工具力的来源 方函式:还记得之前提到的建构式模式吗? 只要提供一个原型,就...
接着要来给 Todo 加上与 User 的关联,区分各 User 建立的 Todo。 一个 User...
阿嬷都看得懂的基础 CSS 选择器 小孩子才做选择,我全都要! -民明书房《我那被限制住的想像》 昨...