Java 值拷贝(值传递)与引用拷贝(引用传递)的区别以及数组的Copy
值拷贝
基本数据类型赋值,赋值方式为值拷贝
n2的变化,不会影响到n1点值
引用拷贝
数组在默认情况下是引用传递,赋的值是地址,赋值方式为引用传递,是一个地址
arr2的变化会影响到arr1
详情看代码及运行结果
public class ArrayAssige
{
// 编写一个main方法
public static void main(String[] args)
{
// 基本数据类型赋值,赋值方式为值拷贝
// n2的变化,不会影响到n1点值
byte n1 = 10;
byte n2 = n1;
n2 = 80;
System.out.println("n1=" + n1 + "\nn2=" + n2);
// 数组在默认情况下是引用传递,赋的值是地址,赋值方式为引用传递,是一个地址
// arr2的变化会影响到arr1
byte[] arr1 = { 1, 2, 3 };
byte[] arr2 = arr1;
arr2[0] = 10;
System.out.println("===arr1的元素===");
for(byte i=0;i<arr1.length;i++)
{
System.out.println("arr1[" + i + "]=" + arr1[i]);
}
System.out.println("===arr2的元素===");
for (byte i = 0; i < arr2.length; i++) {
System.out.println("arr1[" + i + "]=" + arr2[i]);
}
}
}
可以明显的看到二者之间的区别
原因
首先我们要明确Jvm的存储方式(大概如图所示)
值拷贝
值拷贝是开辟了新的空间 n1->[10],因为n2=n1,所以n2->[10],又因为n2=80,所以n2->[80]将n2->[10]进行了值的改变
因此,基本数据类型赋值,n2的变化,不会影响到n1点值[结合图进行理解即可]
引用拷贝
一定要结合图理解
以数组为例
数组在默认情况下是引用传递,赋的值是地址,赋值方式为引用传递,是一个地址
arr2的变化会影响到arr1
直接原因是arr1与arr2共用一个空间,arr2并为开辟行的空间、
arr2=arr1是将arr1的地址给了arr2
也就是说,arr1[0] 和 arr[0] 访问的是同一个存储空间,所以二者之间的变化会影响到彼此的变化,三个也是一样(类推)
数组的Copy
创建一个新的数组arr2,开辟新的数据空间,大小 arr1.length
关键字 new
细节 代码里面有详细的解释
看代码
public class ArrayCopy
{
// 编写有一个main方法
public static void main(String[] args)
{
// 将int[] arr1 = {1,2,3};拷贝到 arr2数组,要求数据空间是独立的
byte[] arr1 = { 1, 2, 3 };
// 创建一个新的数组arr2,开辟新的数据空间,大小 arr1.length
byte[] arr2 = new byte[arr1.length]; // 建议用这种方法开辟新空间,进行赋值
// 遍历 arr1,把每个元素拷贝arr2[]到对应的元素位置,建议用这中方法进行赋值,不建议 arr2 = { 1, 2, 3 };
for(byte i=0;i<arr1.length;i++)
{
arr2[i] = arr1[i];
}
// 修改arr2的值用以验证结果
arr2[0] = 100;
System.out.println("===arr1对应的值如下");
for(byte i=0;i<arr1.length;i++)
{
System.out.println("arr1[" + i + "]=" + arr1[i]);
}
System.out.println("===arr2对应的值如下");
for (byte i = 0; i < arr2.length; i++) {
System.out.println("arr2[" + i + "]=" + arr2[i]);
}
}
}
这样就开辟了一个新空间,arr2的改变不会在影响arr1的值(类推)
运行结果
可以看到,操作成功