📜  Java中的数组Array

📅  最后修改于: 2020-03-28 01:54:38             🧑  作者: Mango

数组Array是一组由通用名称引用的相似类型的变量。Java中的数组与C/C++中的数组工作方式不同。以下是有关Java数组的一些要点。

  • 在Java中,所有数组都是动态分配的。
  • 由于数组是Java中的对象,因此我们可以使用成员长度来找到它们的长度。这与C/C++不同,在C/C++中,我们使用sizeof查找长度。
  • 像其他变量一样,也可以在数据类型后使用[]声明Java数组变量。
  • 数组中的变量是有序的,每个变量的索引都从0开始。
  • Java数组也可以用作静态字段,局部变量或方法参数。
  • 数组的大小必须由int值指定,且不能长或短。
  • 数组类型的直接超类是Object
  • 每种数组类型都实现Cloneable和java.io.Serializable接口。

数组可以包含基本数据类型以及类的对象,具体取决于数组的定义。对于基本数据类型,实际值存储在连续的存储位置中。对于类的对象,实际对象存储在堆段中

创建,初始化和访问数组

一维数组:
一维数组声明的一般形式是

type var-name[];
OR
type[] var-name;

数组声明有两个组成部分:类型和名称。type声明数组的基本数据类型。基本数据类型确定组成数组的每个元素的数据类型。像int类型的数组一样,我们还可以创建其他原始数据类型的数组,例如char,float,double或用户定义的数据类型(类的对象)。因此,数组的元素类型决定了数组将保存的数据。
例:

// 可用的声明
int intArray[];
int[] intArray;
byte byteArray[];
short shortsArray[];
boolean booleanArray[];
long longArray[];
float floatArray[];
double doubleArray[];
char charArray[];
//数组 MyClass
MyClass myClassArray[];
Object[]  ao,        // 数组对象
Collection[] ca;  // Collection数组,类型不确定

尽管上述第一个声明确定了intArray是一个数组变量的事实,但实际上不存在任何数组。它只是告诉编译器this(intArray)变量将保存整数类型的数组。要将intArray与实际的物理整数数组链接,您必须使用new分配内存并将其分配给intArray。

用Java实例化数组

声明数组时,仅创建数组的引用。要实际创建数组或为数组提供内存,您可以这样创建一个数组:new应用于一维数组的一般形式如下所示:

var-name = new type [size];

在这里,type指定要分配的数据的类型,size指定数组中元素的数量,而var-name是链接到数组的数组变量的名称。也就是说,要使用new分配数组,必须指定要分配的元素的类型和数量。
例:

int intArray[];    // 声明数组
intArray = new int[20];  // 分配内存给数组

或者

int[] intArray = new int[20]; // 把上面两个声明结合成一句

注意 :

    1. new分配的数组中的元素将自动初始化为零(对于数字类型),false(对于布尔值)或null(对于引用类型)。
    2. 获取数组是一个两步过程。首先,必须声明所需数组类型的变量。其次,您必须使用new分配用于保存数组的内存,并将其分配给数组变量。因此在Java中,所有数组都是动态分配的。

数组文字

在已知数组大小和数组变量的情况下,可以使用数组文字。

 int[] intArray = new int[]{ 1,2,3,4,5,6,7,8,9,10 };
 // 声明数组文字
  • 该数组的长度决定了所创建数组的长度。
  • 无需在最新版本的Java中编写新的int []部分

使用for循环访问Java数组元素

数组中的每个元素都可以通过其索引进行访问。索引以0开头,以(总数组长度-1)结束。可以使用Java for 循环访问数组的所有元素。

// accessing the elements of the specified array
for (int i = 0; i < arr.length; i++)
  System.out.println("Element at index " + i +
                                " : "+ arr[i]);

实现方式:

// Java展示创建数组,把一些值放入数组,然后打印内部的值
class GFG
{
    public static void main (String[] args)
    {
      // 声明int的array.
      int[] arr;
      // 给长度=5的int数组分配内存.
      arr = new int[5];
      // 初始化第一个元素
      arr[0] = 10;
      //  初始化第2个元素
      arr[1] = 20;
      //继续
      arr[2] = 30;
      arr[3] = 40;
      arr[4] = 50;
      // 访问数组元素
      for (int i = 0; i < arr.length; i++)
         System.out.println("打印值,索引 " + i +
                                      " : "+ arr[i]);
    }
}

输出:

打印值,索引 0 : 10
打印值,索引 1 : 20
打印值,索引 2 : 30
打印值,索引 3 : 40
打印值,索引 4 : 50

您还可以使用foreach循环访问Java数组

对象数组

对象数组的创建方式类似于原始类型数类型的数组,其创建方法如下。

Student[] arr = new Student[7]; //student是用户定义的类

studentArray包含七个内存空间,每个内存空间可以容纳1个学生对象。必须使用学生类的构造函数实例化学生对象,并且应将它们的引用分配给数组中的数组元素。以下方式。

Student[] arr = new Student[5];
// Java展示创建用户定义类的对象数组
class Student
{
    public int roll_no;
    public String name;
    Student(int roll_no, String name)
    {
        this.roll_no = roll_no;
        this.name = name;
    }
}
// Student对象数组
public class GFG
{
    public static void main (String[] args)
    {
        // 声明整数数组.
        Student[] arr;
        // 分配内存.
        arr = new Student[5];
        // 初始化第一个元素
        arr[0] = new Student(1,"mango");
        // 初始化第2个元素
        arr[1] = new Student(2,"doc");
        // 继续
        arr[2] = new Student(3,"文档");
        arr[3] = new Student(4,"dharmesh");
        arr[4] = new Student(5,"mohit");
        // 访问元素
        for (int i = 0; i < arr.length; i++)
            System.out.println("在index " + i + " : " +
                        arr[i].roll_no +" "+ arr[i].name);
    }
}

输出:

在index 0 : 1 mango
在index 1 : 2 doc
在index 2 : 3 文档
在index 3 : 4 dharmesh
在index 4 : 5 mohit

如果我们尝试访问超出数组大小的元素会发生什么?

JVM抛出ArrayIndexOutOfBoundsException来指示已使用非法索引访问了数组。索引为负或大于或等于数组的大小。

class GFG
{
    public static void main (String[] args)
    {
        int[] arr = new int[2];
        arr[0] = 10;
        arr[1] = 20;
        for (int i = 0; i <= arr.length; i++)
            System.out.println(arr[i]);
    }
}

运行时错误

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
    at GFG.main(File.Java:12)

输出:

10
20

多维数组

多维数组是数组的数组,该数组的每个元素都包含其他数组的引用。这些也称为锯齿数组。通过在每个维上附加一组方括号([])来创建多维数组。例子:

int[][] intArray = new int[10][20]; //2D数组
int[][][] intArray = new int[10][20][10]; // 3D数组
class multiDimensional
{
    public static void main(String args[])
    {
        // 声明和初始化2D数组
        int arr[][] = { {2,7,9},{3,6,1},{7,4,2} };
        // 打印2D数组
        for (int i=0; i< 3 ; i++)
        {
            for (int j=0; j < 3 ; j++)
                System.out.print(arr[i][j] + " ");
            System.out.println();
        }
    }
}

输出:

2 7 9
3 6 1
7 4 2

将数组传递给方法

像变量一样,我们也可以将数组传递给方法,例如,下面的程序将数组传递给方法sum来计算数组的值之和。

// Java展示将数组传递给方法
class Test
{
    // 测试代码
    public static void main(String args[])
    {
        int arr[] = {3, 1, 2, 5, 4};
        //把数组传递给m1
        sum(arr);
    }
    public static void sum(int[] arr)
    {
        // 求和
        int sum = 0;
        for (int i = 0; i < arr.length; i++)
            sum+=arr[i];
        System.out.println("数组的和 : " + sum);
    }
}

输出:

数组的和 : 15

从方法返回数组

和往常一样,方法也可以返回数组。例如,下面的程序从方法m1返回一个数组。

// Java展示从方法返回数组
class Test
{
    // 测试代码
    public static void main(String args[])
    {
        int arr[] = m1();
        for (int i = 0; i < arr.length; i++)
            System.out.print(arr[i]+" ");
    }
    public static int[] m1()
    {
        // 返回array
        return new int[]{1,2,3};
    }
}

输出:

1 2 3

数组的类对象

每个数组都有一个关联的Class对象,与其他所有具有相同组件类型的数组共享。

// Java展示数组的类对象
class Test
{
    public static void main(String args[])
    {
        int intArray[] = new int[3];
        byte byteArray[] = new byte[3];
        short shortsArray[] = new short[3];
        // String数组
        String[] strArray = new String[3];
        System.out.println(intArray.getClass());
        System.out.println(intArray.getClass().getSuperclass());
        System.out.println(byteArray.getClass());
        System.out.println(shortsArray.getClass());
        System.out.println(strArray.getClass());
    }
}

输出:

class [I
class java.lang.Object
class [B
class [S
class [Ljava.lang.String

说明:

  1. 字符串“ [I”是类对象“数组类型为int的数组”的运行时类型签名。
  2. 任何数组类型的唯一直接超类是java.lang.Object
  3. 字符串“ [B”是类对象“数组类型为字节的数组”的运行时类型签名。
  4. 字符串“ [S”是类对象“数组类型为short的数组”的运行时类型签名。
  5. 字符串“ [L”是类对象“数组类型的数组”的运行时类型签名,跟随类名。

数组成员

现在您知道数组是一个类的对象,而数组的直接超类是Object类。数组类型的成员如下所示:

  • public final字段length,包含数组的长度,长度可以是正数或零。
  • 所有成员都从类Object继承;不继承的对象的唯一方法是其克隆方法。
  • 公共方法clone()重写类Object中的克隆方法,并且不引发任何检查的异常

克隆数组

  • 当克隆一维数组时,例如Object [],将对新数组执行“深层复制”,该新数组包含原始数组元素的副本(而不是引用)。
    // Java 展示克隆clone一个维度数组
    class Test
    {
        public static void main(String args[])
        {
            int intArray[] = {1,2,3};
            int cloneArray[] = intArray.clone();
            // 打印false
            System.out.println(intArray == cloneArray);
            for (int i = 0; i < cloneArray.length; i++) {
                System.out.print(cloneArray[i]+" ");
            }
        }
    }

    输出:

    false
    1 2 3

  • 多维数组的副本(例如Object [] [])是“浅拷贝”,也就是说,它仅创建一个新数组,每个元素数组都引用原始元素数组,但是子数组是共享的。
    // Java 展示拷贝数组
    class Test
    {
        public static void main(String args[])
        {
            int intArray[][] = {{1,2,3},{4,5}};
            int cloneArray[][] = intArray.clone();
            // 打印false
            System.out.println(intArray == cloneArray);
            // 打印true
            System.out.println(intArray[0] == cloneArray[0]);
            System.out.println(intArray[1] == cloneArray[1]);
        }
    }

    输出:

    false
    true
    true