数组基础

数组是相同类型数据的有序集合。其中,每一个数据称作一个元素,每个元素可以通过一个索引(下标)来访问。

数组有以下特点:

  • 长度是确定的。数组一旦被创建,它的大小就是不可以改变的
  • 其元素的类型必须是相同类型,不允许出现混合类型
  • 数组类型可以是任何数据类型,包括基本类型和引用类型
  • 数组有索引的:索引从 0 开始,到 数组名.length-1 结束
  • 数组变量属于引用类型,数组也是对象,数组中的每个元素相当于该对象的成员变量。由于数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中存储的

内存分析

int[] arr = new int[4];
arr[0] = 12;
arr[3] = 47;
arr[2] = 98;
arr[1] = 56;
arr[2] = 66;

上述代码在内存空间中的活动如下图所示:

JavaSE-22-1

可以看到,首先在栈中生成 main() 方法的栈帧,里面存了 arr 变量和它的值 0x01 ,而数组对象在堆中,0x01 就是数组首元素的地址,每个元素都被默认初始化为 0 ,然后依次赋值和更改。

栈中存放局部变量和形参,堆中存放所有 new 出来的东西,方法区暂且不谈。

数组声明和初始化

数组声明

下面两种声明都可以,不过感觉用第一种较多:

  • int[] arr;
  • int arr[];

注意:如果数组只声明,没有后续操作,那么相当于没定义。这跟将数组赋值为 null 是不一样的。只声明而没有后续操作的语句反编译如下:

public class Test
{
  public static void main(String[] args)
  {
  }
}

而将数组赋值为 null 的语句反编译如下:

public class Test
{
  public static void main(String[] args)
  {
    int[] array = null;
  }
}

数组初始化

数组初始化有三种方式:静态初始化、动态初始化和默认初始化。

静态初始化

静态初始化是在定义数组的同时就直接为数组元素分配空间并赋值:

// 完整形式:
int[] arr = new int[]{12,23,45};
// 简化形式(常用):
int[] arr = {12,23,45};

注意:

  • 静态初始化不可指定数组长度,例如:

    int[] arr = new int[3]{12,23,45}; // 错误!
    
  • 声明和创建分开写时,不可以使用静态初始化的简化形式,而要用完整形式,例如:

    // 错误!
    int[] arr1;
    arr1 = {12,23,45};
    // 正确!
    int[] arr2;
    arr2 = new int[]{12,23,45};
    

动态初始化

动态初始化是指数组的定义和数组的赋值分开进行,例如:

int[] arr = new int[3];
arr[0] = 12;
arr[1] = 23;
arr[2] = 45;

默认初始化

数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。

数组默认的初始化值与数组类型相关:

  • byte[] 元素默认初始化为 (byte)0
  • short[] 元素默认初始化为 (short)0
  • int[] 元素默认初始化为 0
  • long[] 元素默认初始化为 0L
  • foat[] 元素默认初始化为 0.0f
  • double[] 元素默认初始化为 0.0d
  • char[] 元素默认初始化为 '\0000'
  • boolean[] 元素默认初始化为 false
  • 引用数据类型元素默认初始化为 null

例如 int[] arr = new int[3]; 语句将 arr 数组中每个元素默认初始化为 0

数组的遍历

数组的遍历一般有两种,分别是普通 for 循环遍历和增强 for 循环遍历。

  • 普通 for 循环遍历

    // 正向遍历
    for(int i=0;i<=9;i++){   
        System.out.println("第"+(i+1)+"个学生的成绩为:"+scores[i]);
    }
    // 反向遍历
    for(int i=9;i>=0;i--){
        System.out.println("第"+(i+1)+"个学生的成绩为:"+scores[i]);
    }
    
  • 增强 for 循环遍历

    // 对scores数组进行遍历,遍历出来每个元素都用int类型的num接收
    // 优点:代码简单 缺点:单纯的增强for循环不能涉及跟索引相关的操作
    int count = 0;
    for(int num: scores){
        count++;
        System.out.println("第"+count+"个学生的成绩为:"+num);
    }