基本数据类型与引用数据类型在内存结构上的区别
经过上一节的学习,咱们对数组有了大致的了解,包括如何定义使用,不清楚的小伙伴戳这里哈,非常详尽!!!
一/ 引入
【案例一】看一下下面的输出结果是多少。
public class TestArray2{
public static void main(String[] args){
int a=10;
int b=a;
b=100;
System.out.println(a);
}
}
毫无疑问,答案是10。
看一下运行结果吧:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mJL3Y4Pp-1658541704882)(D:\Typora图片\image-20220723083519820.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mJL3Y4Pp-1658541704882)(D:\Typora图片\image-20220723083519820.png)]](https://ucc.alicdn.com/images/user-upload-01/89be1a843ff1479eb72f46f0210edcee.png?x-oss-process=image/resize,w_1400/format,webp)
【案例二】看一下下面的输出结果是多少。
public class TestArray2{
public static void main(String[] args){
int[] x={10,20,30};
int[] y=x;
y[0]=100;
System.out.println(x[0]);
}
}
看一下结果:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hFgS0tB6-1658541704886)(D:\Typora图片\image-20220723084023106.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hFgS0tB6-1658541704886)(D:\Typora图片\image-20220723084023106.png)]](https://ucc.alicdn.com/images/user-upload-01/2fcadae72442443e9e6a684465609e07.png?x-oss-process=image/resize,w_1400/format,webp)
这个结果,很多人就会有疑惑了(疑惑是10,还是100)。
数组之所以难,不是在它的使用。而是它底层的原理,你到底有没有弄明白。
别着急,往后看,你会越来越通透。
二/ 内存存储
【案例一】
public class TestArray2{
public static void main(String[] args){
int a=10;
int b=a;
b=100;
System.out.println(a);
}
}
上面的案例一,内存上是如何执行的?
为了方便理解,画图解释,如下:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UifMlIe5-1658541704886)(D:\Typora图片\image-20220723085759058.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UifMlIe5-1658541704886)(D:\Typora图片\image-20220723085759058.png)]](https://ucc.alicdn.com/images/user-upload-01/bcbee59466cc4a96be16defcd07ab3e3.png?x-oss-process=image/resize,w_1400/format,webp)
【案例二】
public class TestArray2{
public static void main(String[] args){
int[] x={10,20,30};
int[] y=x;
y[0]=100;
System.out.println(x[0]);
}
}
上面的案例二,内存上又是如何执行的?
之前我们说过变量,变量在内存中:
1.是栈内存中的小容器,类型定义了只能存储这种东西。
2.容器中只能存一份。
①int[] x={10,20,30};
现在可以看到,x是一个数组,三个数是不能像变量那样存入一个空间的。
先来看一下int[] x={10,20,30};的标准写法:int[] x=new int[]{10,20,30};。
new是新建的意思。
:star:==以后只要见到new关键字,相当于在堆内存空间中申请开辟了一块新的空间。==
既然新建了一块空间,那这块空间长啥样呢?
就是new关键字后面的内容,即开辟一块int[]数组类型的空间。
那数组类型的空间又长啥样?
:star:==数组在堆内存中的空间形态,是一串连续的地址。==
每一个小格子存的是int类型的数据。
整个开辟空间并存完东西的过程,叫做 数组的初始化。
如下图:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LfzcIvyC-1658541704886)(D:\Typora图片\image-20220723092015246.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LfzcIvyC-1658541704886)(D:\Typora图片\image-20220723092015246.png)]](https://ucc.alicdn.com/images/user-upload-01/b64752549d6e43019504838ba71c85e9.png?x-oss-process=image/resize,w_1400/format,webp)
:question: 既然创建完成了,那么如何把10,20,30存入x空间里面呢?
既然在堆内存中是一串连续的地址。
那么,就把第一个地址交给x处理。
:star: ==x里面存的其实是地址(门牌号)。==
我们可以通过x里面存放的地址,找到数据在堆内存里面存储的位置。
第一个位置找到了,后面的是连续的,就都找到了。
现在暂时理解为是地址,其实是一个HashCode,以后再说这个。
如下图:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sKveXRdz-1658541704887)(D:\Typora图片\image-20220723092747594.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sKveXRdz-1658541704887)(D:\Typora图片\image-20220723092747594.png)]](https://ucc.alicdn.com/images/user-upload-01/993e49c13f684f78a6641289a741e5f4.png?x-oss-process=image/resize,w_1400/format,webp)
② int[] y=x;
第二步,继续创建一个y空间,名字叫y,存储类型为int[]数组类型。
y空间的值是x给的。
x里面存的是一个地址。
那么就是,==x将自己空间的地址,复制了一份,交给了y。==
如下图:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EODeruvx-1658541704887)(D:\Typora图片\image-20220723093325417.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EODeruvx-1658541704887)(D:\Typora图片\image-20220723093325417.png)]](https://ucc.alicdn.com/images/user-upload-01/c2bb605cb8124c86ad22a916d1007e9c.png?x-oss-process=image/resize,w_1400/format,webp)
既然y里面存的是地址,那么就可以通过这个地址访问到堆内存中的数据。
③y[0]=100;
再来看最后一步,这行代码的含义就是:
通过y里面存储的地址,找到堆内存中的数据(即10所在的位置)。
然后在常量区内复制了一份100,交给了堆内存中第一个位置。(将第一个数据,改成了100)
这里是y[0],就是第一个位置,即10。所以覆盖的就是10啦。
如下图:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qnU3iYJr-1658541704888)(D:\Typora图片\image-20220723094149809.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qnU3iYJr-1658541704888)(D:\Typora图片\image-20220723094149809.png)]](https://ucc.alicdn.com/images/user-upload-01/551c2562dc7b46e9b85535bf9e15b199.png?x-oss-process=image/resize,w_1400/format,webp)
④ System.out.println(x[0]);
虽然输出的是x[0],但是x里面的地址指向的堆内存的数据,发生了变化。
第一个数据已经变成了100,所以最后输出,就是100啦。
:red_car:为了方便大家理解,在这里再举个小例子。可以对照着看我上面画的图哈。
小王(x)和小明(y)两个人,都有同一个仓库的钥匙(地址)。
现在小明(y)将仓库里面的西瓜拿走了,装入了菠萝。
过一会,小王(x)再次打开仓库,里面存放的就是菠萝啦。
三/ 总结
(1)基本类型变量空间存储的是值,传递的是值,如【案例一】。
一个改变,另一个不变。
(2)引用类型变量空间存储的是地址(引用),传递的是地址(引用),指向同一个空间。
空间内数据改动了,那就都会改动,如【案例二】。
一个改变,另一个跟着改变。
(3)所有的变量空间都存储在栈内存里。(简单来说,等号左边的东西在栈内存里面)
变量空间可以存储基本数据类型,也可以存储引用数据类型。
如果变量空间存储的是基本数据类型,存储的是值,一个变量改变,另一个不会跟着改变。
(每一个变量里面存储的是一个固定的值,别人变化和我无关)。
如果变量空间存储的是引用数据类型,存储的是地址(引用),一个变量地址对应的值改变,另一个跟着改变。