Java中数组详解

本文详细介绍了Java中的数组,包括数组的定义、初始化、使用,作为方法参数和返回值的情况,数组的应用,以及二维数组的概念和操作。在Java中,数组是存放相同类型数据的集合,初始化有动态和静态两种方式。文章还讨论了数组拷贝的四种方法,以及浅拷贝和深拷贝的区别。最后提到了JVM的五大内存区域与数组的存储关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 数组的定义及初始化
  • 数组的使用
  • 数组作为方法的参数及返回值
  • 数组应用
  • 二维数组

数组的定义及初始化

首先,我们要了解什么是数组。数组是存放相同类型数据的集合,数组的内存分布是连续的

我们创建数组一般有三种方式:

int[] arr = new int[]{1,2,3};  //动态初始化
int[] arr = {1,2,3};  //静态初始化 也产生了对象
int[] arr = new int[3]; //定义数组

数组的初始化可以:

1、动态初始化:数据类型[] 数据名称 = new 数据类型 {初始化数据};

2、静态初始化:数据类型[] 数据名称 = {初始化数据};  (比较常用)

3、定义数组:要注意定义数组并没有初始化数组,只是指定了数组的大小,即就是在堆上给数组开辟了一块连续的空间。

两种异常:我们创建数组的时候容易出现两种异常:
       

int[] arr = {};

这种看起来是我们的静态初始化,不一样的就是初始化大括号里没有数据,这说明我们数组长度为0,所以不能进行数组的访问,否则会造成数组越界异常(java.lang.ArrayIndexOutBoundsException)
 

int[] arr = null;
System.out.println(arr.length);

null在引用类型中的地位就相当于基本类型(int)中的0。我们定义arr数组初始化为null,获取长度时对arr进行操作相当于操作null,会报出空指针异常(java.lang.NullPointerException)

数组的使用

定义完数组后,我们就要操作一个数组啦

1.获取数组arr长度  

int[] arr = {1,2,3};
System.out.println(arr.length);

2.访问数组通过下标来访问,注意数组下标是从0开始的,下标属于[0,length-1]
 

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

这会输出什么呢---[I@16d3586   其实这就类似于c语言中数组存放首元素的地址,不过这个诡异的数字是地址的哈希码,而且地址和哈希码是一一对应的关系。

3.遍历数组:遍历数组就是访问数组的元素,有三种方式
①用for循环遍历数组
 

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

②for-each循环遍历数组

int[] arr = {1,2,3};
//x是用来接收arr数组中的元素,arr是要遍历的数组
for (int x: arr) { 
   System.out.println(x);
}

我们会发现他们两个的不同之处就是for-each循环不能通过下标来访问数组

③Array.toString()直接访问数组--使用时必须导入java.util.Arrays包

int[] arr = {1,2,3};
System.out.println(Arrays.toString(arr)); //将数组以字符串形式输出

数组作为方法的参数及返回值

数组作为方法的参数:

 public static void printArr(int[] arr1) {
        for (int x: arr1) {
            System.out.println(x);
        }
    }

    public static void main(String[] args) {
        int[] arr = {1,2,3};
        printArr(arr);
    }

这样可以依次打印出数组的元素,实际上就是这样的:方法名arr是一个引用,传参的时候按照引用传参。

数组作为方法的返回值:

我们原来可以返回int,float,boolean ....,其实数组也可以当做参数返回的。注意返回的是你new出来的数组,接收当然必须也是同类型数组。

 public static int[] transform(int[] arr) { //不改变原来的数组把数组大小扩大为原来的两倍,并返回
        int[] tmp = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            tmp[i] = arr[i]*2;
        }
        return tmp;
    }

    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        int[] arr2 = transform(arr);
        System.out.println(Arrays.toString(arr2));
    }

数组的应用

数组转字符串:方便打印

   public static void main(String[] args) {
        int[] arr = {1,2,3};
        String newArr = Arrays.toString(arr);
        System.out.println(newArr);
    }

如何自己实现数组转化为字符串呢?其实就是遍历数组字符串拼接的工作啦。。

    public static String tostring(int[] arr) {
        String ret = "[";
        for (int i = 0; i < arr.length; i++) {
            ret += arr[i];
            if(i != arr.length-1) {
                ret += ",";
            }
        }
        ret += "]";
        return ret;
    }


    public static void main(String[] args) {
        int[] arr = {1,2,3};
        System.out.println(tostring(arr));
    }

数组拷贝:

数组的拷贝共有四种方式,对于数组当中如果是简单类型,就是深拷贝。如果是引用类型,那么就是浅拷贝。

1、for循环进行拷贝

int[] array = {1,2,3,4,5};
int[] array2 = new int[array.length];
for (int i = 0; i < array.length; i++) {
    array2[i] = array[i];
}
System.out.println(Arrays.toString(array2));


2、System.arraycopy拷贝

 arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
        //src:代表源数组
        //srcPos:从源数组的pos位置开始拷贝
        //dest:目的数组
        //destPos:目的数组的位置
        //length:要拷贝的长度
  int[] array = {1,2,3,4,5};
  int[] array2 = new int[array.length];
  System.arraycopy(array,0,array2,0,array.length);
  System.out.println(Arrays.toString(array2));


3、Array.copyOf拷贝

 copyOf(int[] original, int newLength)
 //original:源数组
 //newLength:拷贝的长度

 

  int[] arr = {1,2,3};
  int[] arr2 = Arrays.copyOf(arr,arr.length); //arr2只是存放拷贝完的引用
  System.out.println(Arrays.toString(arr2));


4、数组名.clone    clone是Object的方法,返回一个副本

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

那么arrayCopycopyOf区别是什么?

①返回值:arrayCopy返回类型是void,copyOf返回类型是int[](具体的类型)
②代码层次:Array.copyOf()底层调用System.arraycopy()
③速度:System.arraycopy()速度更快(native)

这四种拷贝方式对于简单类型是深拷贝,直接运用于引用类型来说是浅拷贝,若要深拷贝,还要拷贝对象。。ps:后续需补充 

------------

浅拷贝只是拷贝了引用,两个引用指向同一块空间,通过其中一个引用改变对象的值,通过另一个引用访问该对象时值也是改变的;深拷贝不仅拷贝了其引用,还拷贝了其对象。通过一个引用改变对象的值,不影响另一个引用和对象。 

可变参数编程:

    public static int sum(int...array) {
        int ret = 0;
        for(int x: array) {
            ret += x;
        }
        return ret;
    }
    public static void main(String[] args) {
        System.out.println(sum(1,2,3,4,5));
        int[] array = {1,2,3,4,5};
        System.out.println(sum(array));
        //匿名数组
        System.out.println(sum(new int[]{1,2,3,4,5}));
    }

 

 二维数组

定义:数据类型[][] 数组名称 = new 数据类型[行数][列数] {初始化数据};
 

    int[][] array1 = {{1,2,3},{4,5,6}};
    int[][] array2 = new int[][]{{1,2,3},{4,5,6}};
    int[][] array3 = new int[2][3];  //定义 没有初始化
    int[][] array4 = new int[2][]; //可以不写列

 二维数组的分布

打印二维数组:

 

 Arrays.deepToString();

用法和一维数组大同小异。。。不再赘述后续补充。。

=====================================================================================

补充JVM的五大内存区域划分:

1、程序计数器:存放下一条执行的指令的地址。(很small一块)

2、java虚拟机栈:主要用来存放局部变量表

3、本地方法栈:主要用来调用native()方法。存放native方法的局部变量。(native()是由C/C++代码实现的方法,一般出现在源码中)

4、堆:主要来存放对象(new)的

5、方法区:用于存储已经被虚拟机加载的类信息、Class对象

ps:常量池:主要用来存放字符串常量。在JDK1.7以前,常量池存放在方法去。JDK1.7开始,挪到了堆里

        每个线程都会有三块独立的内存区域:程序计数器、java虚拟机栈、本地方法栈

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值