Java数组的使用

前言

       这里我使用的是IDEA编译器进行演示

数组的创建与初始化

创建格式:

T[] 数组名 = new T[N]

T表示数组存放的数据类型,N表示数组的大小。
T[] 表示数组的类型。

这里要注意和C语言不同的是C语言使用类似int arr[10]这样的结构进行创建数组,而Java使用int[] 直接表明这就是一个数组,体现了Java语言具有简单性,通俗易懂。

数组有三种初始化方式:

int[] arr1 = new int[10];
int[] arr2 = new int[]{1,2,3,4,5,6};
int[] arr3 = {1,2,3,4,5,6};

我们来拆分一下上面三种方式:
首先类似:

T[] array = new T[N];

这种创建形式时,我们叫作动态初始化,这种的特点就是创建的数组所有的元素都是0.
在这里插入图片描述
在这里插入图片描述
然后就是类似下面的:

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

这种我们称为静态初始化,这种就直接对数组每个元素进行了赋值。

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

这种初始化和上面的是一样的,只是简写而已(少写了new int[]),这种就更方便书写。

静态初始化是不能写类似int[] arr = new int[3]{1,2,3}的,也就是第二个中括号是不可以写大小的,数组的大小编译器会更具{ }里面的数据进行确定~~

如果使用的是动态初始化,不同的类型对应不同的默认值~~

这里特别记忆一下存放boolean类型的数组每一个元素默认值是false
在这里插入图片描述

如果数组中存储元素类型为引用类型,默认值为null

特殊情况

如果你想分步创建的话,你可以使用下面两种形式:

        int[] arr;
        arr = new int[3];
        int[] arr;
        arr = new int[]{1,2,3};

下面的创建方式是不允许的:
在这里插入图片描述

数组的访问与遍历

访问一个元素

这里可以直接通过访问数组的单个元素,可以借助下标~~

    public static void main(String[] args) {
        int[] arr = new int[]{1,2,5,6,8,9,0};
        System.out.println(arr[2]);
    }

在这里插入图片描述

遍历数组所有元素

1.可以使用循环来直接遍历数组,和C语言是一样的,当时Java里面我们可以直接使用.length来直接得到数组的大小~~

        int[] arr = new int[]{1,2,5,6,8,9,0};
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }

在这里插入图片描述

IDEA编译器可以直接输入fori然后按回车,for循环语句就直接输出来了。

2.我们还可以使用for(数据类型+变量名 :数组名){} 来遍历整个数组元素。

        int[] arr = new int[]{1,2,5,6,8,9,0};
        for (int x: arr) {
            System.out.print(x+" ");
        }

在这里插入图片描述
3.数组直接转字符串,然后直接输出。

        int[] arr = new int[]{1,2,5,6,8,9,0};
        System.out.println(Arrays.toString(arr));

在这里插入图片描述

我们使用的是Arrays里面封装好的方法,它可以直接将数组转变为字符串[数组每一个元素],每一个元素后面会加一个逗号和空格。

引用类型讲解

基本类型变量与引用类型变量的区别

       这里的基本数据类型就是我之前文章里写过的八大基本数据类型,该变量空间中直接存放的是其所对应的值;而引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在空间的地址。

数组是实际上就是一个引用类型变量,数组名存放的是数组的地址,数组名的地址实际上就是数组所引用的对象的地址,这个对象就是数组包含的数组内容。

在这里插入图片描述
在这里插入图片描述
我们通过打印数组名,发现这是一堆奇怪的数字组合,这一堆数字中4eec7777就是数组所引用的对象的地址。

JVM内存的分布

JVM内存一共可以划分为五大空间:
在这里插入图片描述

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

这里我们只关心Java虚拟机栈和堆~~
Java虚拟机栈会存放我们定义的变量和方法,数组名也是会存放在这里,而对象则会存放在堆里

我们从上面了解到数组名包含的就是数组所指向的对象的地址,然后我们可以画一下内存图,这里为了方便,只画Java虚拟机栈和堆这两个内存空间。

在这里插入图片描述

练习

我们来画一下内存分布图:

    public static void func1() {
        int a = 10;
        int b = 20;
        int[] arr = new int[]{1,2,3};
    }

在这里插入图片描述

首先a是基本类型变量,所以a包含的数值就是10,直接入栈,然后是b也是一样,压栈,接着是数组arr压栈,由于数组是应用类型变量,所以是存放的是对象的地址,然后数组压栈~~

    public static void func2() {
        int[] array1 = new int[3];
        array1[0] = 10;
        array1[1] = 20;
        array1[2] = 30;

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

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

这里我用视频来演示一下压栈过程:

JVM内存画图

这里我来简单描述一下,首先array1入栈,array1引用的对象放在堆里,由于是动态初始化,所以开始时每一个元素都是0,接着就是修改数组元素。
然后是array2入栈,array2引用的对象放在堆里,由于是静态初始化,所以开始时array2所引用的对象的内容就是1,2,3,4,5;接着是修改了两个数组元素。
array1=array2 相当于把array2的值赋给了array1,也就是array1现在装的是array2所引用的对象的地址,所以array1的数组元素修改也影响到了array2,毕竟这两个变量现在所引用的对象是一样的~~

这里要注意的是如果原本array1所引用的对象是不是现在没有变量去引用了,不用当心内存泄漏,Java是有垃圾回收机制的,所以这块内存如果没有变量去引用就会被回收掉~~

数组传参和返回问题

时刻保持清醒,Java是没有指针的概念,也就意味着你无法进行取地址解引用等操作,这体现了Java的安全性,学过C语言的铁汁们都知道指针是很危险的,一不小心就内存泄漏,野指针非法访问等问题~~

我们来铺垫一下C语言的知识点:

形参的改变是不会影响实参

在Java中的基本类型变量也是一样的:

    public static void number(int a){
        a += 10;
    }
    public static void main(String[] args) {
        int a = 10;
        System.out.println(a);
    }

在这里插入图片描述

但是,在Java中数组名可以像普通变量一样相互赋值,也就是地址可以交换或者改变,从而改变所引用的对象。所以数组名可以直接传参,形参接收实参的内容,意味着形参引用的对象就是实参引用的对象,所以形参修改数组是会影响到对象的,也就意味着实参也跟着修改~~

    public static void increase(int[] array){
        for (int i = 0; i < array.length; i++) {
            array[i] *= 2;
        }
    }
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4};
        System.out.println(Arrays.toString(arr));
        System.out.println("扩大两倍后:");
        increase(arr);
        System.out.println(Arrays.toString(arr));
    }

在这里插入图片描述

同样的,如果你在方法里创建好了数组,想要返回数组也是可以的,直接返回数组名即可~~

    public static int[] increase(int[] array){
        int[] arr = new int[array.length];
        for (int i = 0; i < array.length; i++) {
            arr[i] = array[i] * 2;
        }
        return arr;
    }
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4};
        System.out.println(Arrays.toString(arr));
        System.out.println("扩大两倍后:");
        int[] arr2 = increase(arr);
        System.out.println("arr数组:"+Arrays.toString(arr));
        System.out.println("arr2数组:"+Arrays.toString(arr2));
    }

在这里插入图片描述

null的介绍

当你创建的数组没有对象时,你可以赋值一个null

int[] arr = null;

在这里插入图片描述

如果你对null的数组进行访问的话,就会报出空指针异常!!!
注意Java确实没有指针的概念,这个空指针异常只是名字就叫作空指针异常而已~~

在这里插入图片描述

Arrays

这个Arrays里面包含很多方法供我们使用,里面也有很多重载,上面我们就知道数组转字符串,这里还有二分查找的方法~~

在这里插入图片描述

这里不一一介绍,想要了解的可以查阅官方帮助文档手册~~
后面的文章我也会去讲解~~

二维数组

二维数组的创建与初始化

先看代码:

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

你要分步也是可以的~~

值得注意的是Java的二维数组如果进行动态初始化是一定要给出行数的~~

我来解释一下:在C语言中我们知道二维数组其实就是有一个又一个一维数组构成的,在Java中我们会明显感受到这个内容。

为什么Java一定要知道二维数组的行数才给创建呢?
二维数组也是引用类型变量,在Java虚拟机栈也是存储的是地址,那这是谁的地址呢?除了自己的地址,那肯定存的是自己的成员(一维数组)的地址
所以如果不知道行数也就不知道要开辟多少个空间来保存多少个地址~~

对比C语言,C语言在传参二维数组的时候为什么要知道二维数组的列数,行数却可以不需要知道呢?
站在C语言的角度,C语言需要开辟一整块空间来保存数组内容,所以C语言是一定要知道这个二维数组的每个成员(也就是一维数组)有多大的,给出列数意味着给出了每一个一维数组的具体大小,这样C语言就可以一次一个一维数组进行开辟空间了,最后二维数组也就随之构建好了,根本就用不到行数。
但是只给行数不给列数就不知道每一个一维数组有多大,就无法进行空间的开辟~~

看到这里大家是不是还有疑惑,就是Java不需要知道一维数组的大小吗?
当然不需要了,可以这样理解,Java中我们需要知道被引用的对象的地址,至于对象是多大不需要关心,我们只需要知道对象的地址~~
所以你会发现其实二维数组的成员(一维数组其实是可以不一样大的)~~

我拿 int[][] array2 = new int[][]{{1, 2, 3}, {4, 5, 6}};来说明一下:
我们来看一下Java这个二维数组内存分布图:
在这里插入图片描述

在这里我们明显看到二维数组实质就是由一维数组构建的~~

我们来验证一下吧:

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

在这里插入图片描述

注意array是动态初始化,由于存储元素类型为引用类型,所以默认值为null
这里要注意了不要去遍历这种null数组哦~~
否则会报空指针异常的~~

二维数组的访问与遍历

遍历方式一

通过上面的解析,我们如果需要遍历二维数组的话,可以使用两个循环,通过.length来得知数组大小~~

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

在这里插入图片描述

遍历方式二

    public static void print(int[][] array){
        for (int i = 0; i < array.length; i++) {
                System.out.println(Arrays.toString(array[i]));
            }
    }
    public static void main(String[] args) {
        int[][] array = new int[4][];
        int[][] array2 = new int[][]{{1,2,3}, {4, 5, 6}};
        int[][] array3 = {{1,2},{3,4},{5,6}};
        System.out.println("array2:");
        print(array2);
        System.out.println("array3:");
        print(array3);
    }

在这里插入图片描述

上面提到Java中的二维数组的成员可以不一样大的,我们来看一下吧:

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

在这里插入图片描述

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

在这里插入图片描述

这里我们知道当我们要使用Arrays.toString的时候传参需要传的是数组名(可以理解成地址)~~
之后它就顺着这个地址将数组的内容转换成字符串了~~

二维数组的传参与返回

不同于C语言,二维数组可以直接传参过去,不需要列数的说明,而C语言是一定要把列数传递过去的~~

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

返回二维数组就不多说了,也是可以直接返回的~~

    public static int[][] creatArray(){
        int[][] arr = {{1},{2,3},{4,8,9}};
        return arr;
    }

    public static void main(String[] args) {
        int[][] array = creatArray();
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[i].length; j++) {
                System.out.print(array[i][j]+" ");
            }
            System.out.println();
        }
    }

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/604813.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

24V转3.8V用什么芯片方案-AH8310

在将24V降压至3.8V的电源转换中&#xff0c;AH8310是一个理想的选择。这款芯片是一款降压转换器&#xff0c;输入电压范围为4.5V至36V&#xff0c;输出电压可调&#xff0c;峰值电流可达1.5A。AH8310采用SOT23-6封装&#xff0c;内置MOS&#xff0c;适用于各种应用场合&#xf…

modprobe: can‘t open ‘modules.dep‘: No such file or directory

使用modprobe会提示modprobe: cant open modules.dep: No such file or directory 直接输入depmod即可。 如果depmod没有效果&#xff0c;则需要重新配置编译你的根文件。 在busybox配置界面进入linux Module Utilities, 上下键选择depmod&#xff0c;并按 y 选中&#xff0c…

【vue+vue-treeselect】根据指定字段,如isLeaf(是否末级节点),设置只允许末级节点可以选

1、当项目有特殊要求&#xff0c;必须根据某个字段的值去判断&#xff0c;是否节点可以选&#xff0c;即使已经是末级节点了&#xff0c;还是需要根据字段判断是否禁用 &#xff08;1&#xff09; :flat"true"一定要设置 (2)获取数据源的时候&#xff0c;设置下禁用…

leetcode91.解码方法(动态规划)

问题描述&#xff1a; 一条包含字母 A-Z 的消息通过以下映射进行了 编码 &#xff1a; A -> "1" B -> "2" ... Z -> "26" 要 解码 已编码的消息&#xff0c;所有数字必须基于上述映射的方法&#xff0c;反向映射回字母&#xff08;可…

NineData亮相2024中国移动算力网络大会

4月28日至29日&#xff0c;2024中国移动算力网络大会在苏州召开。大会以“算力网络点亮AI新时代”为主题&#xff0c;全面展示了中国移动最新算力网络成果与能力。江苏省委常委、苏州市委书记刘小涛&#xff0c;副省长赵岩出席开幕式并致辞。内蒙古自治区副主席白清元出席。中国…

【JAVA语言-第20话】多线程详细解析(二)——线程安全,非线程安全的集合转换成线程安全

目录 线程安全 1.1 概述 1.2 案例分析 1.3 解决线程安全 1.3.1 synchronized关键字 1.3.1.1 同步代码块 1.3.1.2 同步方法 1.3.2 使用Lock锁 1.3.2.1 概述 代码示例 1.4 线程安全的类 1.4.1 非线程安全集合转换成线程安全集合 线程安全 1.1 概述 指如果有多…

JavaEE企业级开发中常用的JDK7和JDK8的时间类

JDK7时间类 全世界的时间有一个统一的计算标准 在同一条经线上的时间是一样的 格林威治时间 简称GMT 计算核心 地球自转一天是24小时 太阳直射正好是12小时 但是误差太大 现在用原子钟来代替 用铯原子震动的频率来计算时间&#xff0c;作为世界的标准时间UTC 中国标准时间…

Dockerfile实践java项目

目的&#xff1a;用java项目测试dockerfil部署&#xff08;前提是安装好了docker&#xff09; 部署准备文件如下 1. java项目 java项目demo地址 https://gitee.com/xiaoqu_12/dockerfileDemo.git 或者百度网盘直接下载打包好的jar包 链接&#xff1a;https://pan.baidu.com/s/…

Ansible---inventory 主机清单

一、inventory 主机清单 1.1、inventory介绍 hosts配置文件位置&#xff1a;/etc/ansible/hosts Inventory支持对主机进行分组&#xff0c;每个组内可以定义多个主机&#xff0c;每个主机都可以定义在任何一个或多个主机组内。 1.2、inventory中的变量 Inventory变量名含义…

数值计算方法——大题题型总结

目录 一、绝对误差限、相对误差限 1.1 例题 1.2 解题套路 1.3 题解 二、敛散性、收敛速度 2.1 例题 2.2 解题套路 2.3 题解 三、牛顿迭代法 3.1 例题 3.2 解题套路 3.3 题解 四、割线法 4.1 例题 4.2 解题套路 ​4.3 题解 五、列主元素消去法 5.1 例题 5.…

新版Idea配置仓库教程

这里模拟的是自己搭建的本地仓库环境&#xff0c;基于虚拟机搭建利用gogs创建的仓库 1、Git环境 你需要准备好git和仓库可以使用github 、gitee等 1.1 拉取代码 本项目使用 Git 进行版本控制&#xff0c;在 gogs 上创建一个个人使用的 git 仓库&#xff1a; http://192.168.…

【Linux】项目自动化构建工具make/makefile的简单使用

使用步骤 1) 编写 创建 makefile 文件 vim makefile用 vim 打开名为 makefile 的文件,存在该文件则打开编辑,不存在则创建并打开.在 makefile 文件中编写需要编译的文件 test:test.cppg -o test test.cpp第一行: 冒号左侧为编译后的可执行文件名,可以随便取. 冒号右侧为依赖…

vue2项目升级到vue3经历分享4

后端重构&#xff0c;如果接口做好抽象封装&#xff0c;只需要考虑jar之间的兼容性问题&#xff0c;jdk版本不变&#xff0c;基本不用做太大的调整&#xff0c;但是前端就不一样&#xff0c;除了vue框架本身&#xff0c;css的调整&#xff0c;改起来更是让人头疼。前面写了vue2…

Linux与windows网络管理

文章目录 一、TCP/IP1.1、TCP/IP概念TCP/IP是什么TCP/IP的作用TCP/IP的特点TCP/IP的工作原理 1.2、TCP/IP网络发展史1.3、OSI网络模型1.4、TCP/IP网络模型1.5、linux中配置网络网络配置文件位置DNS配置文件主机名配置文件常用网络查看命令 1.6、windows中配置网络CMD中网络常用…

C++进阶之路:深入理解编程范式,从面向过程到面向对象(类与对象_上篇)

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

Mysql 基础 - 常见 子句

算数运算符 > < > < !/<> 逻辑运算符 3i in is null is not null 2l limit like 2o or 、order by 1a and ib between and 1n not and、or 、not、 in、 orderby、 limit、 like、 between...and、 is null 、is not null

我独自升级崛起怎么下载 游戏下载教程分享

《我独自升级&#xff1a;崛起》这款游戏核心聚焦于激烈的战斗与角色的持续成长。新加入的玩家首要任务是熟悉基础攻击模式&#xff0c;随后深入探索技能组合策略与连贯招式的艺术&#xff0c;同时掌握防守与躲避技巧&#xff0c;这些都是战斗中不可或缺的关键。随着战斗的持续…

那个在买珠宝的年轻人

金价搭上过山车&#xff0c;今年以来价格一路飙涨。 珍珠身价同步飙升&#xff0c;晋级珠宝圈“新宠”。 文玩圈“减龄”&#xff0c;盘珠串不再只是“老头乐”。 月薪3000的年轻人&#xff0c;悄悄实现“宝石”自由。 黄金珠宝走俏&#xff0c;这届年轻人到底有着怎样的珠宝…

Baidu Comate智能编码助手 -----AI编程帮你解放双手

目录 Baidu Comate是什么&#xff1f; Baidu Comate如何安装&#xff1f; 在VSCode上安装Baidu Comate插件 Baidu Comate如何使用&#xff0c;有哪些功能&#xff1f; 1.代码解释 2.代码注释 使用感受 如何体验 Baidu Comate是什么&#xff1f; Baidu Comate智能编码助手…

网络编程入门之UDP编程

欢迎各位帅哥美女来捧场&#xff0c;本文是介绍UDP网络编程。在这里&#xff0c;你会见到最详细的教程&#xff1b;细致到每一行代码&#xff0c;每一个api的由来和使用它的目的等。 目录 1.UDP相关API 1.1.两个类 1.2.两个类中的方法 2.UDP编程 2.1.大体框架 2.2.内容构…
最新文章