0


【JavaSE】数组的赋值机制(值拷贝与引用传递)、数组拷贝、数组反转与数组扩容

本专栏为 JavaSE 的学习笔记及相关项目,专栏长期免费更新 ❤️ ❤️ ❤️
⭐️往期回顾:

  • 【JavaSE】Java中的流程控制(分支控制、循环控制、嵌套)
  • 【JavaSE】【计算机系统基础】原码、反码、补码及位运算详解(重点)在这里插入图片描述

文章目录


1 数组引入

✈️ 数组是 Java 里的引用数据类型,可以存放多个同一类型的数据,通俗点来说,数组就是一组数据。

1.1 数组的使用

⭐️star 1: 动态初始化

方式一:声明的同时分配存储空间

数据类型

[ ]

数组名

=

new
数据类型

[ 大小 ];

方式二:先声明后分配存储空间

数据类型
数组名

[ ];

数组名

=

new
数据类型

[ 大小 ];

比如我们需要创建一个含有五个元素的数组,每个元素都用于存储学生的成绩,示例代码如下:

Scanner in =newScanner(System.in);// 声明数组并开辟空间double[] score =newdouble[5];// 赋值for(int i =0; i <5; i++){
    score[i]= in.nextDouble();}

上述代码声明了一个长度为5的数组score,其中score[ 0 ]指向第一个元素,依此类推,注意,在数组中,索引是从 0 开始的,示意图如下:
在这里插入图片描述
⭐️star 2: 静态初始化
适用于知道数组具体有多少元素和具体值的情况。

数据类型
数组名

[ ] = {

元素值1

元素值2

元素值3

… …};

1.2 数组的注意事项

  1. ⭐️ 数组是多个相同类型数据的组合,实现对数据的统一管理,如果声明了 int 类型的数组,那么其元素值均为 int 类型,但是其也满足类型转换规则,如下代码是可以编译通过的:
double[] number ={12.3,1.23,2.44,100};// 符合自动类型转换
  1. ⭐️ 数组中的元素可以是基本数据类型与引用数据类型,但是不可以混用,比如 String 类型的数组中不能存在 int 类型元素;

  2. ⭐️ 如果数组创建后没有进行赋值,则会使用默认值,具体如下表:
    数据类型默认值int0short0byte0long0float0.0double0.0booleanfalseStringnull

  3. ⭐️ 数组属于引用类型,数组型的数据是对象。

1.3 数组的赋值机制

1.3.1 基础数据类型的值拷贝

我们先来讨论一下基础数据类型的赋值机制,观如下代码:

publicclassMain{publicstaticvoidmain(String[] args){int a =10;int b = a;
        b =20;System.out.println("a = "+ a);System.out.println("b = "+ b);}}

🍑 代码运行结果为 a = 10,b = 20,可见 a 没有受到 b 的影响,我们把这种赋值机制叫做 值拷贝

1.3.2 数组的引用传递

🍑 数组在默认情况下是引用传递,赋的值是地址,赋值方式为引用传达。
一脸懵? 没关系,我们直接看代码:

publicclassMain{publicstaticvoidmain(String[] args){int[] array1 ={1,2,3,4,5};int[] array2 = array1;// 把 array1 赋给 array2
        array2[0]=1000;// 修改 array2// 输出 array1System.out.print("array1 : ");for(int i =0; i < array1.length; i++){System.out.print(array1[i]+" ");}}}

🍎 结果如下图:
在这里插入图片描述
通过观察输出结果我们发现,明明我们修改的是 array2 数组的值,可 array1 也受到了影响,这种传值机制就是所谓的引用传递,下面我们来细说:

✈️ 在Jvm中,内存大致被分为3块,栈、堆和方法区。当我们声明数组并初始化 array1 时,jvm 在堆开辟了数组大小的空间,而在栈内存中则存储着指向堆空间的地址,可以理解为门牌号。而这个变量存储的值就是门牌号,当我们将 array1 赋值给了 array2 时,相当于告诉了 array2 :“array1 的地址我告诉你了奥!” 这时,arrray2 便也指向了 array1 开辟的那一部分空间,因此我们修改 array2 的值的时候,实际上是更改了 array1 的值(array1 与 array2 指向同一块儿内存!)。具体示意图如下:
在这里插入图片描述


2 数组的拷贝

✈️ 我们了解到数组的赋值方式为引用传递,那么,我们该如何拷贝数组其不会影响原数组的值呢?下面我们来看一段代码,这段代码实现了对 array1 数组的拷贝:

publicclassMain{publicstaticvoidmain(String[] args){int[] array1 ={1,2,3,4,5};// 创建一个新数组 array2, 并开辟新的空间// 大小为 array1.lengthint[] array2 =newint[array1.length];// 数组拷贝for(int i =0; i < array1.length; i++){
            array2[i]= array1[i];}// 修改 array2[0]
        array2[0]=1000;// 输出 array1 array2System.out.print("array1 : ");for(int i =0; i < array1.length; i++){System.out.print(array1[i]+" ");}System.out.print("\narray2 : ");for(int i =0; i < array2.length; i++){System.out.print(array2[i]+" ");}}}

🍎 实现结果如下:
在这里插入图片描述
此时,我们发现,修改 array2 的元素值对 array1 就不会产生影响了,这与之前引用传递的不同是:我们重新给 array2 开辟了新的空间,示意图如下:
在这里插入图片描述


3 数组反转

🍑 给定一个数组 array = {1,2,3,4,5,6},让你把它反转,即改为 array = {6,5,4,3,2,1} 你有什么思路吗?
参考思路如下:

  1. ⭐️ array[ 0 ] 与 array[ 5 ] 进行交换,结果为{6,2,3,4,5,1};
  2. ⭐️ array[ 1 ] 与 array[ 4 ] 进行交换,结果为{6,5,3,4,2,1};
  3. ⭐️ array[ 2 ] 与 array[ 3 ] 进行交换,结果为{6,5,4,3,2,1};
  4. ⭐️ 一共交换了 array.length/2 次, 且每次交换的元素为 array[ i ] 与 array[ length -1 - i]

🍑 参考代码:

publicclassArrayReverse{publicstaticvoidmain(String[] args){int[] array ={1,2,3,4,5,6};for(int i =0; i < array.length/2; i++){int temp = array[i];
            array[i]= array[array.length -1- i];
            array[array.length -1- i]= temp;}// 输出结果for(int i =0; i < array.length; i++){System.out.print(array[i]+" ");}}}

以上仅仅是一种实现方式,小伙伴们也可以尝试上面讲过的数组拷贝的方法,逆序拷贝 array1 也可以实现同样的功能哦!


4 数组扩容

🍑 我们来看一个实际需求:

要求实现动态给数组添加元素的效果,实现对数组的扩容:
1)原数组使用静态分配,int[ ] arr = {1, 2, 3};
2) 添加的新元素直接放到数组最后 arr = {1, 2, 3, 4}

🍑 参考思路如下:

  1. ⭐️ 定义初始数组 arr;
  2. ⭐️ 定义一个新的数组 arrNew;
  3. ⭐️ 遍历 arr 数组,一次将元素拷贝给 arrNew;
  4. ⭐️ 将 4 赋值给 arNew[ arrNew.length - 1]

看到这,你可能会有些疑惑:什么?定义一个新数组???这不是浪费空间吗??
不用担心!!!Java 的垃圾回收机制会帮你解决,我们来看下面的示意图:
在这里插入图片描述

我们将扩容后的新数组 arrNew 赋值给 arr ,则原数组 arr 开辟的空间

0x0011

未被使用,因此被垃圾回收释放,此时我们再通过 arr 访问的实质上是 arrNew 开辟的新空间!!!
🍎 话不多说!看代码!!

publicclassArrayAdd{publicstaticvoidmain(String[] args){int[] arr ={1,2,3};int[] arrNew =newint[arr.length +1];// 数组拷贝for(int i =0; i < arr.length; i++){
            arrNew[i]= arr[i];}
        arrNew[arr.length]=4;// 原数组扩容
        arr =arrNew;// 查看结果for(int i =0; i < arr.length; i++){System.out.print(arr[i]+" ");}}}

🌟 结果:
在这里插入图片描述

4.1 数组动态扩容

🍎 我们可以思考一下,如果上述的需求需要我们不停的添加元素,直到用户希望退出时打印结果,我们该如何优化?
这里可以结合我们上一篇所学的

do while

+

break

实现,程序直接进入循环询问需要添加的元素,添加后询问是否退出,当输入 n 时,退出程序并打印结果,具体代码如下:

importjava.util.Scanner;publicclassArrayAdd{publicstaticvoidmain(String[] args){int[] arr ={1,2,3};Scanner in =newScanner(System.in);do{int[] arrNew =newint[arr.length +1];// 数组拷贝for(int i =0; i < arr.length; i++){
                arrNew[i]= arr[i];}System.out.println("输入需要添加的元素: ");int number = in.nextInt();
            arrNew[arr.length]= number;// 原数组扩容
            arr =arrNew;// 是否需要继续扩容System.out.println("是否继续?(y/n): ");if(in.next().charAt(0)=='n')break;}while(true);System.out.println("结果为: ");// 查看结果for(int i =0; i < arr.length; i++){System.out.print(arr[i]+" ");}}}

😎 实现结果:
在这里插入图片描述


写在最后

🌟以上便是本文的全部内容啦,后续内容将会持续免费更新,如果文章对你有所帮助,麻烦动动小手点个赞,非常感谢 ❤️ ❤️!
如果有问题,欢迎私信或者评论区!
共勉:“其实一直陪伴你的,是那个了不起的自己。”
在这里插入图片描述

标签: java

本文转载自: https://blog.csdn.net/m0_60353039/article/details/124258466
版权归原作者 Nezuko627 所有, 如有侵权,请联系我们删除。

“【JavaSE】数组的赋值机制(值拷贝与引用传递)、数组拷贝、数组反转与数组扩容”的评论:

还没有评论