【Java学习—(6)数组的定义与使用】

先复习一下方法的递归吧

程序能实现方法递归的核心原因:当在程序中调用另一个函数时,当前程序会暂缓执行,直到函数调用结束,当前程序才会继续执行。

在什么场景下能够使用方法递归呢?

  1. 大问题可以拆分为若干个子问题的解
  2. 拆分后的子问题与原问题除了数据规模不同,其解决思路完全相同
  3. 存在递归的终止条件(拆分是有终点的,不会无限制的拆分下去)

如何写出正确的代码:最核心的问题就是关注这个方法的语义(功能)(深思这句话)

我假设这个方法已经实现好了,你就调用别人写好的函数来辅助你解决问题。


前面的章节知识

1 数据类型

2 类型转换

3 运算符

4 逻辑控制

5 输入输出

6 方法的使用

方法递归



7 数组的定义与使用

7.1 什么是数组

数组本质上就是让我们能够“批量“创建相同类型的变量。

一次定义N个相同类型的变量,我们就把这种结构称之为数组。

7.2 数组的创建与动态初始化

数组的动态初始化有两种方法:

  1. 数据类型[] 数组名称 = new 数组类型[]{初始化数据}
  2. 数据类型[] 数组名称 = new 数据类型[num] num 表示当前数组的最大元素个数
int[] arr1 = new int[]{1,2,3,4};
int[] arr2 = new int[4];

还有数组的静态初始化:

数据类型[] 数组名称 = {初始化数据};

int[] arr3 = {1,2,3,4};

注意:数组的静态初始化是语法糖,javac 编译之后就是动态初始化.

7.3 数组的使用

我们要使用一个数组,首先要知道这个数组可以存储多少个元素,就要知道这个数组的长度,那怎样得到数组的长度呢?

获得一个数组的长度(最多保存的元素个数):

直接使用数组名称.length

int[] arr1 = new int[]{1,2,3,4,5};
int[] arr2 = new int[5];
arr1.length; //得到arr1的长度
arr2.length; //得到arr2的长度

那如何访问数组元素呢?

数组名称[要访问的元素相比较与第一个元素的偏移量]

数组名称[元素的索引]

解释一下元素的索引:数组的索引从0开始,最后一个元素的索引是arr.length - 1


为什么索引要从0开始呢?

索引其实就是”偏移量“,相较于数组的第一个元素的单位长度,第一个元素的偏移量不就是0么

数组在内存中存储时,每个元素之间都是顺序存储的,保存的数组就是数组的首元素的地址,要找到其他元素,只要知道其他元素相较于第一个元素的距离就能找到

int[] arr = new int[]{1,2,3,4,5};
System.out.println(arr[0]);//数组的第一个数
System.out.println(arr[4]);//数组的最后一个数

遍历数组的每个元素,可以有两种方法:

  1. 使用for循环,索引数组每个元素的下标,实现遍历数组的每个元素
  2. 使用 JDK1.5引入的for-each循环,增强型for循环

第一种方法:

int[] arr = new int[]{1,2,3,4,5,6};
for(int i = 0; i < arr.length; i++){
    System.out.println(arr[i] + ",");
}

这种方法遍历的数组,arr[i] 是真正拿到了数组的每个元素,修改的话,也是直接修改数组。

第二种方法:

int[] arr = new int[]{1,2,3,4,5,6};
for(int i:arr){
    //i指的是从数组的第一个元素开始取值,第一次把第一元素的值复制一份给i
    //第二次循环把第二个元素的值复制一份给i,
    //依次类推,直到整个数组都遍历结束
    System.out.println(i + ","); 
}

for-each循环遍历数组,只能读取数组的元素值,无法进行修改!!

i 是原数组每个元素的值拷贝,并不是实实在在的数组元素


7.4 数组与方法之间的关系

数组是引用数据类型,具体就是整型数组的引用

7.4.1 数组作为方法的参数

创建一个方法,接收任意类型的整型数组并打印

public static void prinArr(int[] num){};

在实际代码中,在主方法中调用的参数是实参,在普通方法中调用的是形参,只不过拷贝的是实参的地址,具体的往下看

7.4.2 关于引用数据类型的理解问题

JVM把数据内存划分为6个区域,在这里就只说”栈区“ 和 ”堆区“。

方法的调用就是在栈区进行的,每个方法的调用过程。就是一个栈帧的入栈以及出栈过程。

“栈” —先进后出的结构。方法中的局部变量和形参都在栈中存储,当方法调用结束出栈时,临时变量都会被销毁。

就像一个碗一样,先加的饭在下面,后加的饭在上面,先吃掉的一定是后加的饭

JVM 的另一块内存区域称为“堆区”,所有对象都在堆区存取数组对象,类的实例化对象,接口的对象。


public static void main(String[] args){
    int[] arr = new int[]{10,20};
    swapArr(arr);
    System.out.println("arr[0]= " + arr[0] + "arr[1]= " + arr[1]);
}
public static void swapArr(int[] arr){
    int temp = arr[0];
    arr[0] = arr[1];
    arr[1] = temp;
}

我们来具体看这个代码:

int[] arr = new int[]{10,20}; //程序的执行都是从右到左
//等号右边表示:数组对象,在堆上开辟内存空间进行存储
//等号左边表示:数组的引用

在这里插入图片描述

引用就是起了一个“别名”,保存的数值就是该对象的地址

对于数组对象来说,数组引用实际上是保存了数组的首元素地址。

swapArr(arr);//arr是实参
//实参到形参的传递仍然满足值传递,只是把main -> arr存储的数组地址拷贝一份复制
//给swapArr->arr,这样他们在栈中存储的变量就指向了堆中的同一个地址,也就是数组首元素的地址

在这里插入图片描述

在swapArr执行:

public static void swapArr(int[] arr){
    int temp = arr[0];
    arr[0] = arr[1];
    arr[1] = temp;
}

在这里插入图片描述

swapArr中,对于arr的元素进行了交换,因为arr存储了数组的地址,与main->arr是同一个地址,所以在swapArr中进行的数组元素交换对于main->arr是可见的。


本质上来说,main->arrswapArr->arr指向了堆中的同一块内存区域!!


System.out.println("arr[0]= " + arr[0] + "arr[1]= " + arr[1]);

此时 swapArr方法已经销毁,

在这里插入图片描述

在程序中看见new关键字,就一定在堆中开辟了新的空间,要操作堆中的对象,必须要通过引用来进行,必须知道这个对象的名字才能进行操作。


7.5 数组的工具类

在JDK中看到某些类后加s,这种类都是工具类,提供了大量有用的方法,直接调用就可以。

Arrays - 数组的工具类,包含数组转字符串的方法,数组排序的方法,等等操作数组的各种方法都在这个类中,我们直接通过类名称来调用

Collections - 集合的工具类

将数组对象转为字符串对象: Arrays.toString

int[] arr = {1,2,3};
String str = Arrays.toString(arr);
System.out.println(str);

拷贝数组Arrays.copyOf

Arrays.copyOf(int[] original, int newLength); 
//返回拷贝的新数组
//复制指定的数组,用零截取或填充(如有必要),以便复制具有指定的长度。 

注意

  1. 若新数组长度 < 原数组长度, 部分拷贝。从原数组的第一个元素开始复制值,直到元素个数达到新数组的长度停止。
  2. 若新数组的长度 = 原数组的长度。 全部拷贝
  3. 新数组的长度 > 原数组长度。全拷贝,剩余的元素用该数据类型的默认值来补。

在运行程序时,出现ArrayIndexOutOfBoundsException 报错,说明是数组越界了。


总结

数组对象就是实实在在的在堆中保存数据的实体,new出来的都在堆中存储。

数组的引用就是给这块数组对象起了个名字,保存这个数组对象的首地址而已。


要是对大家有所帮助的话,请帮我点个赞吧。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值