✨你好啊,我是“ 罗师傅”,是一名程序猿哦。
🌍主页链接:楚门的世界 - 一个热爱学习和运动的程序猿
☀️博文主更方向为:分享自己的快乐 briup-jp3-ing
❤️一个“不想让我曾没有做好的也成为你的遗憾”的博主。
💪很高兴与你相遇,一起加油!

前言

目标:Java基础编程,熟练Java开发语法和规则,养成良好编程习惯

数组概述

​ 数组,表示一块连续的内存空间,可用来存储多个数据(元素),要求元素类型要一致

数组定义

  • 数据类型[] 数组名(推荐)

    1
    int[] arr1;
  • 数据类型 数组名[]

    1
    int arr1[];

数组内存理解

attention:

  • 数组是引用数据类型,用来存储一个引用值(可理解为地址值
  • 数组/变量 没有进行初始化,不可直接使用

数组初始化

定义数组(开辟栈空间内存)的同时,给其赋上初值,就叫做数组的初始化!

动态初始化

  • 格式:数据类型[] 数组名 = new 数据类型[数组长度]

  • 案例:

    1
    int[] arr1 = new int[3];
  • 注意:

    • new是一个关键字,表示数组在堆内存区域开辟内存空间
    • 等号两边的数据类型要一致(继承、实现不一定)
    • 数组长度必须要有,可以>=0(一般大于0),但不能为负数

内存构成

数组名标识的那块内存(栈空间),存放了一个引用值(地址值),通过该地址值可以找到堆空间相应内存(用来存放数组中所有元素)

堆空间内存存在默认初始化:整数型=0,浮点数=0.0,引用类型=null,字符类型=\u0000

1
2
3
4
5
6
/* 输出结果为:[I@15db9742
* [ : 当前的空间是一个数组类型
* I : 当前数组容器中所存储的数据类型
* @ : 分隔符
* 15db9742 : 堆空间十六进制内存地址
*/

数组下标

数组的下标的区间为[0, 数组长度-1]

minIndex = 0, maxIndex = length - 1

  • 通过下标可以访问数组中元素

    1
    int a = arr[1];
  • 通过数组下标给数组元素赋值

    1
    arr[1] = 100;
  • 结合循环来赋值或者取值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int[] arr = new int[4];
    for(int i = 0; i < 4; i++) { // 循环赋值
    arr[i] = i + 1;
    }
    for(int i = 0; i < 4; i++) { // 循环取值
    System.out.println(arr[i]);
    }
    for(int i: arr) { // foreach主要用来遍历,赋值不会对原来的数据产生影响
    System.out.println(arr[i]);
    }

数组长度

数组长度:是指在一个数组中,可以存放同一类型元素最大数量

获取数组长度固定格式:数组名.length

1
2
intp[] arr = new int[4];
System.out.println(arr.length);

数组长度注意事项:

  • 数组长度,必须在创建数组对象的时候就明确指定
  • 数组长度,一旦确定,就无法再改变
  • 数组长度,可以>=0 (一般大于0),但不能为负数

数组默认值

数组在创建时,会开辟2块内存,数组名对应栈空间那块内存,数组元素会 存放在堆空间。

堆空间数组每一个元素位置上,存在相应的默认值,要么为0,要么为0.0, 要么为null。

1
2
3
4
5
6
7
8
9
10
// byte、short、int、long类型数组中的默认值为0
int[] a = new int[4]; // 默认4个数据全是0
// float、double类型数组中的默认值为 0.0
double[] d = new double[4]; // 默认4个数据全是0.0
// boolean类型数组中的默认值为false
boolean[] d = new boolean[4]; // 默认4个数据全是false
// char类型数组中的默认值为 '\u0000'
char[] d = new char[4]; // 默认4个数据全是 '\u0000'
// 引用类型数组中的默认值为null
String[] d = new String[4]; // 默认4个数据全是null

静态初始化

在创建数组的同时,直接初始化数组元素的值,就称为数组的静态初始。

静态初始化格式:

  • 完整版格式:

    1
    2
    // 数据类型[] 数组名 = new 数据类型[]{元素1,元素2,...};
    int[] arr = new int[]{1,2,3,4,5};
  • 简化版格式:

    1
    2
    // 数据类型[] 数组名 = {元素1,元素2,...};
    int[] arr = {1,2,3,4,5};

注意:数组静态初始化书写方式要严格按照上述两种方式!

错误展示:

1
2
3
4
5
//错误方式1:不能明确数组长度
int[] arr4 = new int[3]{1,2,3};
//错误方式2:简化版格式必须严格按照上述格式书写,不能分两行书写
int[] arr5;
arr5 = {1,2,3};

内存补充

  • 两个数组内存结构图
  • 使用数组赋值

数组异常

索引越界异常

1
2
int[] arr = new int[4];
System.out.println(arr[4]); // java.lang.ArrayIndexOutOfBoundsException: 4

空指针异常

1
2
3
int[] arr = new int[4];
arr = null;
System.out.println(arr[0]); // java.lang.NullPointerException

arr = null 这行代码,意味着变量arr将不会在保存数组的内存地址,我 们通过arr这个标识符再也找不到堆空间数组元素,因此运行的时候会抛出 NullPointerException 空指针异常。

工具类

java.util.Arrays 类,是JavaSE API中提供给我们使用的一个工具类,这个类 中包含了操作数组的常用方法,比如排序、查询、复制、填充数据等,借助它我 们在代码中操作数组会更方便。

Arrays中的常用方法:

  • toString方法
    • 可以把一个数组变为对应的String形式
  • copyOf方法
    • 可以把一个数组进行复制 该方法中也是采用了arraycopy方法来实现的功能
  • sort方法
    • 可以对数组进行排序
  • binarySearch方法
    • 在数组中,查找指定的值,返回这个指定的值在数组中的下标,但是查找之 前需要在数组中先进行排序,可以使用sort方法先进行排序
  • copyOfRange方法(了解)
    • 也是复制数组的方法,但是可以指定从哪一个下标位置开始复制 该方法中也是采用了arraycopy方法来实现的功能
  • fill(了解)
    • 可以使用一个特定的值,把数组中的空间全都赋成这个值

扩展案例

选择排序

插入排序

希尔排序

看我的这篇博客即可:基础篇-interview-heima

数组拷贝

数组的长度确定后便不能修改,如果需要数组存放更多元素,可以通过创建长度更长的新数组,然后先复制老数组内容到新数组中,再往新数组中放入额外的元素。

1
2
3
4
5
6
7
8
9
// java.lang.System arraycopy() 复制数组功能
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
// src: 需要 被 复制的目标数组
// srcPos: 从目标数组的哪一个位置开始复制
// dest: 需要把数据复制到另外一个新的数组中
// destPos: 把数据复制到新数组的时候,需要把数据从什么位置开始复制进去
// length: 复制的目标数组的长度

案例:定义一个方法,传递一个数组对象给它,其将数组长度扩大到原来的2倍返回。

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
int[] arr = new int[] { 1, 2, 3, 4 };
int[] newArr = dilatation(arr);
System.out.println(Arrays.toString(newArr));
}

private static int[] dilatation(int[] arr) {
// TODO Auto-generated method stub
int[] b = new int[arr.length * 2];
System.arraycopy(arr, 0, b, 0, arr.length);
return b;
}

二维数组

定义格式

格式1:

  • 数据类型[][] 数组名 = new 数据类型[一维长度m][二维长度n];
  • 表示二维数组的元素数量,即可以存放多少个一维数组
  • 表示每一个一维数组,可以存放多少个元素

格式2:

  • 数据类型[][] 数组名 = new 数据类型[一维长度m][];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 第一种格式
int[][] arr = new int[2][3];
System.out.println(arr); // [[I@b684286
/*
* [[I@b684286
*
* [[: 2个中括号就代表的是2维数组
* I: 数组中存储的数据类型为
* int 15db9742: 十六进制内存地址
*/

// 二维数组的每一个 元素都对应着(一维数组)地址
System.out.println(arr[0]); // [I@2a139a55
System.out.println(arr[1]); // [I@15db9742

//第二种定义格式
int[][] arr2 = new int[2][];
//输出arr2中2个元素值,默认为null、null
System.out.println(Arrays.toString(arr2));
//给二维数组的每个元素赋值
arr[0] = new int[2];
arr[1] = new int[3];

内存结构

  • 一维数组内存结构:
  • 二维数组内存结构:

可以把二维数组看成一个一维数组,数组的每个元素对应的内存区域中,存放的是一维数组引用值

元素访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// int arr[m][n];
int[][] arr = new int[2][3];
// 存数
arr[0][0] = 11;
arr[0][1] = 22;
arr[0][2] = 33;
arr[1][0] = 11;
arr[1][1] = 22;
arr[1][2] = 33;
// 取数
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
// 注意:m、n的取值都是 [0,length-1] ,注意不要越界,否则会出现异常 ArrayIndexOutOfBoundsException

初始化

1
2
3
4
5
//第一种:完整格式
int[][] arr1 = new int[][]{{1,2,3},{4,5}};

//第二种:简化格式
int[][] arr2 = {{11, 22, 33}, {44, 55}};

综合案例

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

可变参数列表

JDK1.5或者以上版本中,可以使用可变参数列表

格式:

1
2
3
修饰符 返回值类型 方法名(数据类型... 参数名) {
方法体语句;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//普通方法定义
public static void fun(int[] a){
//...
}
//可变参数列表 方法定义
public static void test(int... a){
//...
}
public static void main(String[] args) {
int[] arr = {1,2,3};
//普通方法的调用,只有下面一种形式
fun(arr);
//可变参数列表方法的调用,下面形式都可以
test(); //不传参
test(1); //传递1个元素
test(1,2,3,4); //传递多个元素
test(arr); //传递数组
}

结论:可变参数列表本质上是一个数组,方法中使用可变参数列表,比用数组作参数功能更强大

补充:方法中有一个可变参数同时,还可以存在其他参数

1
2
3
4
public static void test(int a, int... b) {
System.out.println(a);
System.out.println(Arrays.toString(b));
}

注意事项:可变参数和普通参数共存的时候,可变参数必须放到最后一个参数的位置。

总结:

  • 可变参数列表可以接受 0-n个参数
  • 可变参数列表还可以接受数组
  • 可变参数列表必须放在函数参数列表的最右端,且只能出现1次

❤️❤️❤️忙碌的敲代码也不要忘了浪漫鸭!

业精于勤,荒于嬉;行成于思,毁于随。💪