【迷人的爪哇】——Java数组详解

一、数组的概念和定义

  • 数组是一类相同元素的集合。
  • 数组初始化时可以在定义时就初始化,也可以之后通过 new int[] { }进行初始化。
  • 如果数组没有初始化时其默认值就是0(float 是0.0f 、double是0.0、char是/u0000、boolean是false)

Java中数组的写法分为一下三种:

1:

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

是array2的简写。 

 2:

int[] array2 = new int[]{1,2,3,4,5};

 3:

int[] array3 = new int[5];

 array1是一个变量,其存储的是对象的地址。

 在引用变量值存储了对象的地址,引用  指向了/引用了  一个对象。 

 二、数组使用

2.1 元素的访问

  • 当需要访问数组第几个元素时,可以用  数组名[下标]
  • 当需要修改数组元素时,也可以用  数组名[下标]  =  数值   进行修改。
public class Test1 {
    public static void main(String[] args) {
        int[] array1 = {1,2,3,4,5};
        System.out.println(array1[2]);
        array1[2] = 0;
        System.out.println(array1[2]);
    }
}

 注:数组访问时要注意下标的合法性。

2.2 数组的遍历

在Java中数组的长度是  数组名.length 

第一种遍历方法:

public class Test1 {

    public static void main(String[] args) {
        int[] array = {1,2,3,4,5};
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
    }
}
 

 第二种遍历方法:for each

public class Test1 {

    public static void main(String[] args) {
        int[] array = {1,2,3,4,5};
        for(int x: array){
            System.out.println(x);
        }
    }
}

注:

第一种方法和第二种方法的主要区别在于第二种方法没有用到下标,当在遍历数组时需要用到下标判断数据时,就使用第一种方法。

第三种遍历方法:

public class Test1 {

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

 三、数组是引用类型

3.1 初识jvm内存分布

  •  程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址
  • 虚拟机栈(JVM Stack): 与方法调用相关的一些信息,每个方法在执行时,都会先创建一个栈帧,栈帧中包含有:局部变量表、操作数栈、动态链接、返回地址以及其他的一些信息,保存的都是与方法执行时相关的一些信息。比如:局部变量。当方法运行结束后,栈帧就被销毁了,即栈帧中保存的数据也被销毁了。
  • 本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native方法的局部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的
  • 堆(Heap): JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2,3} ),堆是随着程序开始运行时而创建,随着程序的退出而销毁,堆中的数据只要还有在使用,就不会被销毁。
  • 方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域

 例如:

public class Test1 {

    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int[] array = {1,2,3};
   
    }

 思考下面例题:

public class Test1 {

    public static void main(String[] args) {
        int[] array1 = {10,20,30};

        int[] array2 = new int[]{1,2,3,4,5};
        array2[0] = 100;
        array2[1] = 200;

        array1 = array2;
        array1[2] = 300;
        array1[3] = 400;
        array1[4] = 500;
        for (int i = 0; i < array2.length; i++) {
            System.out.println(array2[i]);
        }

    }
}

 答案:

 解析:

 其中最关键的是 array1 = array2 ,array2的地址赋值给了array1,array1就指向了0x22处所指向那块空间,再对array1进行赋值操作时,就是对0X22地址处的数据进行修改,所以打印的结果就为100~500。

3.2 认识null

如果一个引用不指向任何对象,就将它赋值为 null。

public class Test1 {

    public static void main(String[] args) {
        int[] arr = null;
        System.out.println(arr);
    }
}

例题:

public class Test1 {

    public static void main(String[] args) {
       int[] array = {7,8,9};
       func1(array);
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i]+" ");
        }
        System.out.println();
        System.out.println();
        func2(array);
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i]+" ");
        }
        System.out.println();
    }

    public static void func1(int[] array1){
        array1 = new int[]{1,2,3};
    }
    public static void func2(int[] array2){
        array2[0] = 0;
    }
}

答案: 

 

 解析:

本代码中:

func1:用数组作为方法的参数,func1中,array1 又new了一个对象,改变了引用的指向,指向了一个新的地址。对array里的数据不会进行改变。

func2:array2指向的就是array的地址,然后修改数据,改变的就是array数组的内容。

四、数组的应用场景

4.1作为函数的参数

  • 实现一个打印函数:
public class Test1 {

    public static void print(int[] str){
        for (int i = 0; i < str.length; i++) {
            System.out.print(str[i] + " ");
        }
        System.out.println();
    }

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

解析:

数组名作为引用常量传递的是地址,调用方法会在栈上开辟栈帧,通过地址会找到在堆区的数组,进而进行操作。

4.2作为函数的返回值

public class Test1 {

    public static int[] test1(){
        int[] tmp = new int[]{1,2,3,4,5};
        return tmp;
    }

    public static void main(String[] args) {
        int[] ret = test1();
        System.out.println(Arrays.toString(ret));
    }

}

 

解析: 

五、数组练习

1、模拟实现Tostring函数

public class Test1 {

    public static String myToString(int[] arr){
        String tmp = "[";
        if (arr == null){
            return "null";
        }else{
            for (int i = 0; i < arr.length; i++) {
                tmp += arr[i];
                if(i < arr.length - 1){
                    tmp += ",";
                }
            }
        }
        tmp += "]";
        return tmp;
    }

    public static void main(String[] args) {
        int[] array = new int[]{1,2,3};
        String ret = myToString(array);
        System.out.println(ret);
    }
}

2、模拟数组拷贝

public class Test1 {

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

    public static void copyOf(int[] arr,int[] str){
        for (int i = 0; i < arr.length; i++) {
            str[i] = arr[i];
        }
    }
}

 Java中自带有数组拷贝函数:copyOf

public class Test1 {

    public static void main(String[] args) {
        int[] array = {1,2,3,4};
        int[] ret = Arrays.copyOf(array,array.length);
        System.out.println(Arrays.toString(array));
        System.out.println("-----------------------");
        System.out.println(Arrays.toString(ret));
    }
}

 

 注:

当拷贝的数组长度大于原数组的长度,相当于给原数组进行扩容:

Java中也有拷贝数组一部分的函数:copyOfRange、System.arraycopy

 在Java中的from:to:是左闭右开的,所以上面的下标范围是 [1,3)。

深拷贝与浅拷贝:

如果拷贝后的数组不影响原来的数组,那么这个拷贝就是深拷贝,繁殖则为浅拷贝。

六、二维数组

二维数组本质是一维数组,只不过每个元素又是一个一维数组。

6.1 二维数组的语法

public class Test1 {

    public static void main(String[] args) {
        int[][] array1 = {{1,2,3},{4,5,6}};
        int[][] array2 = new int[][]{{1,2,3},{4,5,6}};
        int[][] array3 = new int[3][3];
    }
}

 6.2 遍历二维数组

1、基本遍历数组

public class Test1 {

    public static void main(String[] args) {
        int[][] array1 = {{1,2,3},{4,5,6}};
        int[][] array2 = new int[][]{{1,2,3},{4,5,6}};
        int[][] array3 = new int[3][3];

        for (int i = 0; i < array1.length; i++) {
            for (int j = 0; j < array1[i].length; j++) {
                System.out.print(array1[i][j]+" ");
            }
            System.out.println();
        }
    }

}

 2、foreach

public class Test1 {

    public static void main(String[] args) {
        int[][] array1 = {{1,2,3},{4,5,6}};
        for (int[] tmp : array1) {
            for (int x : tmp) {
                System.out.print(x+" ");
            }
        }
        System.out.println();
    }
}

 

 3、deepToString

public class Test1 {

    public static void main(String[] args) {
        int[][] array1 = {{1,2,3},{4,5,6}};
        System.out.println(Arrays.deepToString(array1));
    }
}

6.3 二维数组的列省略

当列省略时,二维数组为null:

我们也可以指定二维数组的列:

 

这时该数组的每一行的列是不确定的。 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值