说明

这是一个完善了但又不完善的笔记,或许以后会更新

可以参考但请务必超越

源文件


Tools


Typora
PicGo

数组的定义与使用

  1. 啥是数组?
  2. 定义是啥?
  3. 数组咋用?

咸鱼三连。

1.数组的基本用法

1.1 什么是数组

数组:存储一组相同数据类型的数组的集合

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

我们要表示2个数组的时候可以直接创建2个变量

int a = 0;
int b = 0;

那要是一万个,那也太多了,这时候就可以使用数组。

注意:在Java中,数组中包含的变量必须是相同类型

1.2 创建数组

类型[] 数组变量名 = {初始化值}; 
int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};

注意:和C语言不一样,不可以在中括号中输入数据

这样写是直接初始化了内容,内容就是1234567890

还有其他的创建方式

int[] array = new int[3];

这里使用了一个关键字new:实例化一个对象。

意味着:Java当中的数组,也是一个对象,第一种写法虽然没写,但也是一个对象,只不过省略了new int[]

而且这样的创建方式是没有初始化的,只是开辟了空间

所以不省略的写法就是

int[] array = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 0};

注意还是不要在[]里写数字

int arr[]

其实数组也可以这么写,这样就和C语言更相似了

在C语言中使用int arr[],其实arr只是数组的变量,他的类型还是int[],在C中调试的时候也是显示int[]等于多少多少

说到底数组还是int[],只不过在Java中把他改的更顺了一些,int[]是一体的所以放在了一起

虽然可能少数人感觉看的不舒服,实际上C语言才写的不太对...

1.3 数组的使用

获取长度

使用array.length

System.out.println(array.length);

数组的长度不需要像C语言那样再去求了,站在巨人的肩膀上自然就会优化的更好,补足一些缺陷

注意在for循环中不能写=array.length,否则会数组越界

访问元素

数组,是有下标来排列顺序的。从0下标开始,使用的时候使用下标即可

System.out.println(array[5]);

修改数组元素就使用下标改

arr[5] = 10;

数组越界

如果我们访问的时候访问一个-1下标或者其他数组范围外的下标,Java就会直接报错,如果是C语言可能只是个警告或者运行顺利就过去了

这里就提现了Java的安全性,也很严谨

站在巨人的肩膀上

和上面的获取数组长度一样,老大哥C语言确实是有一些问题的,不过也没必要改,经典就是经典。所以有本书叫《C陷阱与缺陷》,没见其他语言的缺陷。这很正常,你觉得他有问题,那你使用他你就得适应,或者开发新语言,优化语言,弥补缺陷,这非常好。

idea 增强for循环

idea提供了一个foreach的快捷输入方式,叫做增强for循环

for (int x : array) {
    System.out.print(x + " ");
}

区别

  • for循环是可以拿到下标的
  • for each是拿不到下标的

假如在数组中找到一个元素返回他的下标,就是用for,如果只是要找到这个元素返回元素,使用for each就可以了。到后面集合中使用的更多一点

在不同的情况下都各有好处,看情况用

Arrays打印

这里还可以借助Java操作数组的工具类Arrays来打印数组

将参数的数组以字符串的形式输出

import java.util.Arrays;

int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
Arrays.toString(array);

可以看到把array这个数组作为参数然后打印了出来

而且还自带[]

2.数组作为方法的参数(重点)

这里先简单讲一点JVM的内容,到后面JVM章节再深入讲解

Java虚拟机栈:就是我们平常说的栈

本地方法栈:跑C/C++代码。JVM实际上是由C/C++代码实现的一个软件而已,所以一定有一些底层的代码是在这里跑的。

:就是我们平常说的堆,存放一些对象

方法区:存放一些静态的变量

程序计数器:存放下一条指令,保证记录下一条指令是要干什么。不能上个厕所回来就不知道接下来要干什么吧

2.1 数组的存储

上面我们创建的数组array,他在JVM是这样存放的

array:存放了变量的地址,就是引用变量。我们一般叫做引用引用指向一个对象。那么这个数组就是一个对象。前面创建的时候也说过。

注意!

看图就很容易理解

引用就相当于C语言的指针嘛,array是数组名也是引用变量

这样理解虽然可以

但是!千万千万注意,反过来引用可不是数组名

就像C语言的指针。他们在别的地方也会使用

null

和C语言的空指针一样,Java中引用可以指向null

注意C语言是大写的,Java是小写

如果我们去求一个指向null数组的长度

空指针异常

不指向任何对象,哪有什么长度

同样适用下标也是空指针异常

什么都没有嘛

2.2 方法中的形参数组

在方法中讲到过,实参和形参

那么数组传给方法的,也是地址

有人叫过按引用传递,其实也可以叫做按值传递

到这里可能很多人都会和C语言混,说白了就是给函数传了个值,这个值是数组的地址嘛

不要想的太复杂

改变引用指向的对象

2个引用指向一个对象

那么能不能1个引用指向多个对象?

那肯定是不可能的

人格分裂?一根吸管同时和多杯水?脚踏多条船?什么狗屁渣男

int[] array = new int[]{1,2,3,4,5};
array = new int[10];   
array = new int[20];
array = new int[30];

所以,引用只会改变指向的对象,不能指向多个对象

指向的是自然最后一个改变的对象

最后还有一个问题:

引用一定是在栈上吗???

不一定:一个变量在不在栈上,是你变量的性质决定的。如果就是一个局部变量,那就在栈上。如果是实例成员变量,那就不一定在栈上了。

3.数组作为方法的返回值

写一个方法,将数组中的每个元素都乘2

public static void func(int[] array) {
    for (int i = 0; i < array.length; i++) {
        array[i] = 2 * array[i];
    }
}

public static void main(String[] args) {
    int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    func(array);
    System.out.println(Arrays.toString(array));
}

通过前面的内容我们知道,实参和形参他们指向一个对象

那么问题来了,func这个方法岂不是把原来的数组直接改变了,如果我们不想改变原来的数组呢?

很简单,在方法的内部创建一个新的数组返回来

public static int[] func(int[] array) {
    int[] ret = new int[array.length];
    //方法中创建一个数组ret
    for (int i = 0; i < array.length; i++) {
        ret[i] = 2 * array[i];
        //把乘2的元素放到ret中
    }
    return ret;
    //返回数组ret
}

public static void main(String[] args) {
    int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    int[] ret2 = func(array);
    //接收数组ret
    System.out.println(Arrays.toString(ret2));
}

4.数组应用(练习)

关于数组的练习题什么的其实很简单,就不多讲了,想查也很多

这里主要说一下关于数组的拷贝

数组拷贝

数组的拷贝其实可以自己写个方法拷贝

//1.一般拷贝
public static int[] copyArray(int[] array) {
    int[] copy = new int[array.length];
    for (int i = 0; i < array.length; i++) {
        copy[i] = array[i];
    }
    return copy;
}

当然,Java提供了几个方法

//2.Java提供的拷贝
//2.1 Arrays.copyOf
int[] copy1 = Arrays.copyOf(array, array.length * 2);
//这里长度设置为*2就相当于扩容。注意Java提供的参数类型是int,所以不能输入小数倍数
System.out.println(Arrays.toString(copy1));

//2.2 Arrays.copyOfRange
int[] copy2 = Arrays.copyOfRange(array, 1, 3);
//Range即可以设定部分拷贝,比如从1下标到3下标
System.out.println(Arrays.toString(copy2));

//2.3 System.arraycopy
int[] copy3 = new int[array.length];
System.arraycopy(array, 0, copy3, 0, array.length);
//设定从原数组的几下标开始,到要拷贝的数组下标几开始,长度是多少
//可以查看System.arraycopy的实现好像不完整?其实是只要带了native字样的方法,都已经由C/C++语言实现了,我们是看不到的
//这些方法有一个特点,就是速度快
System.out.println(Arrays.toString(copy3));

//2.4 clone
int[]copy4 = array.clone();
//就直接克隆,产生一个副本
System.out.println(Arrays.toString(copy4));

既然是拷贝,就会有原数组和新数组,那么这里有两个拷贝的概念

深拷贝:修改新数组,原数组不变

浅拷贝:修改新数组,原数组也变

深拷贝或者浅拷贝都是人为实现的。

5.二维数组

注意:一般情况下无论是什么语言,在内存中二维数组的存储其实都是一行,并不是真的是个表格的类型。

也就是说

二维数组本质上也是一维数组,只不过每个元素又是一个一维数组(二维数组属于特殊的一维数组)

创建

基本语法

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

一般我们可以直接使用{}直接创建一个几行几列的二维数组,例如2行3列

int[][] array = {{1,2,3},{4,5,6}};

和一维数组一样,在Java中中括号内不能输入数字,除非是不初始化的创建方式

完整写法

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

不初始化写法

数据类型[][] 数组名称 = new 数据类型 [行数][列数];

打印

只要记着下标即可

因为是特殊的一维数组,所以可以画一下来理解

那么array.length就可以知道

System.out.println(array.length);//2
System.out.println(array[0].length);//3

一般打印

for循环就可以使用array.lengtharray[i].length来打印

foreach打印

其实就很简单

Java提供的方法

和一维数组一样,Java提供了Arrays.deepToString(),直译也就是深度打印的方法

自动加中括号和逗号

不规则二维数组

这一块就不需要多讲了,一行可能少一个元素嘛,注意使用array.length时小心空指针即可

小头图版权:《鍾空2》by 阿语:钟离好感10纪念 2021年10月26日中午12点01分 pid:93694598

广告位招租
最后修改:2021 年 10 月 28 日 02 : 17 PM
如果觉得我的文章对你有用,请喂饱我!(理直气壮)