基本数据类型与引用数据类型简介,以及做到如何将引用数据输入方法且不改变引用数据
1.基本数据类型指的是简单的数据段,比如Number、String 、Boolean、Null和Undefined;引用数据类型指的是有多个值构成的对象,比如Object 、Array 、Function 、Data。
这里用Number和Array说明一下两类数据的引用赋值上的差异。
对于以下代码,变量a依然是10;
int a = 10;
int b = a;
b = b - 1
对于以下代码,变量a则变为{{1,1},{0,1}};
int[][] a = {{1,1},{1,1}};
int b = a;
b[1][0] = b[1][0] - 1;
如果我们要让a数组不变,变量a依然是{{1,1},{1,1}},则需要通过逐个赋值的方式将a复制到b,并且对b数组进行操作,代码如下:
int[][] a = {{1,1},{1,1}}; int[][] b = new int[2][2]; for(int i = 0;i < 2;i++){ for (int j = 0; j < 2; j++) { b[i][j] = a[i][j]; } } b[1][0] = b[1][0] - 1;
2.整个的测试完整代码:
import java.util.Arrays; public class Test { public static void main(String[] args){ int a = 10; int b = a; b = b - 1; System.out.println("a = " + a); System.out.println("......................"); int[][] a1 = {{1,1},{1,1}}; int[][] b1 = a1; b1[1][0] = b1[1][0] - 1; System.out.println("a1[][] = " + Arrays.deepToString(a1)); System.out.println("......................"); int[][] a2 = {{1,1},{1,1}}; int[][] b2 = new int[2][2]; for(int i = 0;i < 2;i++){ for (int j = 0; j < 2; j++) { b2[i][j] = a2[i][j]; } } b2[1][0] = b2[1][0] - 1; System.out.println("a2[][] = " + Arrays.deepToString(a2)); System.out.println("......................"); } }
3.以下代码更加完整的阐述了以上谈到的点,并将数组输入了方法,且使用了Array.clone()。需要注意的是,在一维数组和二维数组中,Array.clone()的作用是不一样的。一维数组中,Array.clone()是赋值;在二维数组中,Array.clone()则是指向对象。
import java.util.Arrays; public class Test2 { public static void main(String[] args){ new Test2().testMain(); } //主方法,在主方法里引用次方法test、test1 public void testMain() { int[][] inputArr = {{1, 1,}, {1, 1}}; System.out.println("以下说明引用数据类型改变原值的情况,假设我们不想改变inputArr,但做不到:"); System.out.println("未进入方法时,inputArr = " + Arrays.deepToString(inputArr)); int[][] outputArr = test(inputArr); System.out.println("输出outputArr = " + Arrays.deepToString(outputArr)); System.out.println("进入方法后,inputArr = " + Arrays.deepToString(inputArr)); System.out.println("___________________________\n"); System.out.println("以下说明基本数据类型不改变原值的情况,假设我们不想改变inputNum,则做得到:"); int inputNum = 10; System.out.println("未进入方法时,inputNum = " + inputNum); int outputNum = test1(inputNum); System.out.println("输出outputNum = " + outputNum); System.out.println("进入方法后,inputNum = " + inputNum); System.out.println("___________________________\n"); System.out.println("以下说明使用引用数据类型且不改变数据的方法:"); int[][] inputArr1 = {{1, 1,}, {1, 1}}; System.out.println("未进入方法时,inputArr1 = " + Arrays.deepToString(inputArr1)); int[][] tmp1 = new int[inputArr1.length][inputArr1[0].length];//tmp1是通过给每个元素赋值的方式复制了inputArr1 for (int i = 0; i < inputArr1.length; i++) { tmp1[i] = inputArr1[i].clone();//一维Arr.clone是赋值,不是赋地址 } // //下一个循环和上一个循环等价 // for (int i = 0; i < inputArr1.length; i++) { // for (int j = 0; j < inputArr1[0].length; j++) { // System.out.println("i,j = " + i + j ); // tmp1[i][j] = inputArr1[i][j]; // } // } int[][] tmp = inputArr1.clone();//tmp则是通过引用地址复制,等价于tmp = inputArr1,其实根本没有复制 int[][] outputArr2 = test(tmp1); System.out.println("输出outputArr1 = " + Arrays.deepToString(outputArr2)); System.out.println("进入方法后,inputArr1 = " + Arrays.deepToString(inputArr1)); System.out.println("进入方法后,inputArrCopy = " + Arrays.deepToString(inputArr1)); System.out.println("按照逐行.clone,则相当于赋值,它没变___________________________\n"); int[][] outputArr1 = test(tmp); System.out.println("输出outputArr1 = " + Arrays.deepToString(outputArr1)); System.out.println("进入方法后,inputArr1 = " + Arrays.deepToString(inputArr1)); System.out.println("进入方法后,inputArrCopy = " + Arrays.deepToString(inputArr1)); System.out.println("二维数组中,直接使用.clone,依然会改变原来的数组___________________________\n"); } //对于引用数据类型,即使在调用的方法内定义了新的数组outoutArr,inputArr依然会被改变。因为引用数据类型是对堆内存对象进行操作,而不是对变量outputArr进行操作。 public int[][] test(int[][] inputArr){ int[][] outputArr = new int[2][2]; outputArr = inputArr; outputArr[1][1] = outputArr[1][1] - 1; return outputArr; } //对于基本数据类型,即使在方法中直接对inputNum进行操作,依然不改变方法外的inputNum的值。 public int test1(int inputNum){ inputNum = inputNum/2; return inputNum; } }