当前位置: 首页 > news >正文

【Java】数组详解

文章目录

  • 一、数组的基本认识
    • 1.1 数组的概念
    • 1.2数组的创建与初始化
    • 1.3 数组的使用
  • 二、数组的类型 — 引用类型
    • 2.1 JVM 内存分布
    • 2.2 什么是引用类型
    • 2.3 基本类型变量与引用类型变量的区别
    • 2.4 Java 中的 null
  • 三、数组的应用
    • 3.1 保存数据
    • 3.2 函数参数
    • 3.3 函数返回值


一、数组的基本认识

1.1 数组的概念

数组(Array)是一种用于存储相同类型元素的数据结构。它是一组连续的内存位置,每个位置都存储着一个元素,并通过索引来访问和操作这些元素。数组通常用于存储和处理大量的数据,提供了一种有效的方式来组织和访问数据。

1.2数组的创建与初始化

在 Java 中,数组的创建和初始化可以通过以下几种方式进行:

  1. 静态初始化

在静态初始化中,可以直接指定数组的元素值,并在创建数组时进行初始化。语法格式如下:

dataType[] arrayName = {value1, value2, value3, ...};

示例:

int[] numbers = {1, 2, 3, 4, 5}; // 创建并初始化一个包含5个整型元素的数组
  1. 动态初始化

在动态初始化中,需要先创建数组对象,然后通过索引逐个赋值。语法格式如下:

dataType[] arrayName = new dataType[length];

示例:

int[] numbers = new int[5]; // 创建一个包含5个整型元素的数组
numbers[0] = 1; // 给第一个元素赋值
numbers[1] = 2; // 给第二个元素赋值
// ...
  1. 默认初始化

在默认初始化中,数组的元素会根据其数据类型进行默认初始化。例如,整型数组的元素默认值为0,浮点型数组的元素默认值为0.0,布尔型数组的元素默认值为false,引用类型数组的元素默认值为null。示例:

int[] numbers = new int[5]; // 创建一个包含5个整型元素的数组,默认值为0
  1. 使用 Arrays 类的 fill() 方法

Arrays 类中的 fill() 方法可以用指定的值填充数组的所有元素。语法格式如下:

Arrays.fill(arrayName, value);

示例:

int[] numbers = new int[5];
Arrays.fill(numbers, 0); // 将数组的所有元素设置为0

这些是在 Java 中创建和初始化数组的常用方法。根据需求和场景的不同,选择合适的方法来创建和初始化数组。

1.3 数组的使用

数组中元素访问:

在 Java 中,可以使用索引来访问数组中的元素。数组的索引从0开始,表示数组中元素的位置。通过指定索引值,可以获取特定位置的元素值,对其进行读取、修改或其他操作。

下面是使用索引访问数组元素的示例:

int[] numbers = {1, 2, 3, 4, 5};// 读取数组中的元素
int firstElement = numbers[0]; // 获取第一个元素,值为1
int thirdElement = numbers[2]; // 获取第三个元素,值为3// 修改数组中的元素
numbers[1] = 10; // 将第二个元素的值修改为10System.out.println("First element: " + firstElement); // 输出: First element: 1
System.out.println("Third element: " + thirdElement); // 输出: Third element: 3
System.out.println("Modified array: " + Arrays.toString(numbers)); // 输出: Modified array: [1, 10, 3, 4, 5]

需要注意的是,数组索引必须在有效范围内,即从0到数组长度减1。如果指定了超出范围的索引,会导致数组越界异常(ArrayIndexOutOfBoundsException)。

数组的遍历:

在 Java 中,有多种方式可以遍历数组,对数组中的每个元素进行操作。以下是几种常用的数组遍历方法:

  1. for 循环

使用普通的 for 循环可以遍历数组,通过索引逐个访问数组元素。示例:

int[] numbers = {1, 2, 3, 4, 5};
for (int i = 0; i < numbers.length; i++) {int element = numbers[i];// 对每个元素进行操作System.out.println(element);
}
  1. 增强 for 循环(foreach 循环)

增强 for 循环提供了一种简化的语法,可以直接遍历数组中的元素,无需使用索引。示例:

int[] numbers = {1, 2, 3, 4, 5};
for (int element : numbers) {// 对每个元素进行操作System.out.println(element);
}
  1. 使用 Arrays 类的 toString() 方法

使用 Arrays 类的 toString() 方法可以将整个数组转换为字符串表示,方便打印或输出。示例:

int[] numbers = {1, 2, 3, 4, 5};
System.out.println(Arrays.toString(numbers));

二、数组的类型 — 引用类型

2.1 JVM 内存分布

下面是 JVM 的主要内存分布图:

【说明】

  1. 方法区(Method Area):
    方法区是用于存储类的结构信息(如类的字段、方法、构造函数)、运行时常量池、静态变量、即时编译器编译后的代码等数据。它在JVM启动时被创建,并且是所有线程共享的。在较早的JVM版本中,方法区被实现为永久代(Permanent Generation),但在JDK 8及后续版本中,永久代被元空间(Metaspace)取代。

  2. 虚拟机栈(VM Stack):
    虚拟机栈用于存储线程的方法调用和局部变量信息。每个线程在执行时都会创建一个对应的虚拟机栈,栈中的每个元素被称为栈帧(Stack Frame),用于存储方法的局部变量、操作数栈、动态链接、方法返回值等信息。每个方法在执行时都会创建一个对应的栈帧,并随着方法的进入和退出进行入栈和出栈操作。

  3. 本地方法栈(Native Method Stack):
    本地方法栈类似于虚拟机栈,但是它是为执行本地(非Java)方法服务的。它与虚拟机栈的作用相似,但存储的是本地方法的信息。

  4. 堆(Heap):
    堆是用于存储对象实例的区域。在Java程序运行时,动态分配的对象都存储在堆中。堆是Java虚拟机管理的最大一块内存区域,也是所有线程共享的。堆被划分为新生代(Young Generation)和老年代(Old Generation)等不同的区域,其中新生代又包括Eden空间、Survivor空间等。

  5. 程序计数器(Program Counter):
    程序计数器是用于存储当前线程正在执行的字节码指令的地址或索引。它是线程私有的,每个线程都有自己独立的程序计数器。在任何一个时间点,一个线程都只能执行一个方法的代码,也就是所谓的当前方法。程序计数器用于记录线程执行的位置,以便在发生线程切换时能够恢复到正确的执行位置。

此时,我们要理解引用类型,就只需要理解清楚虚拟机栈和堆这两块内存区域

2.2 什么是引用类型

引用类型(Reference Type)是指在Java中,用于引用对象的类型。与引用类型相对应的是基本类型(Primitive Type),用于直接存储数据的类型,如整数、浮点数、字符等。

引用类型可以是类、接口或数组类型。当我们声明一个引用类型的变量时,实际上在内存中为该变量分配了存储空间,这个存储空间可以用来存储对象的引用(内存地址),而不是实际的对象数据

引用类型的变量本身占用的内存空间是固定的,不受对象大小的影响,因为它只存储了对象的引用。通过这个引用,我们可以间接地访问和操作对象的实例变量和方法

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

简单来说,基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值;而引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在空间的地址

例如下面的代码:

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

其中,a和b都是基本类型变量,而arr是引用类型变量。但是,它们都是方法内部的变量,因此其存储空间的都被分配在func方法的栈帧中。由于a和b是基本类型变量,它们内部保存的就是给自己初始化的值,即1 0 和 20;而arr是引用类型变量,其内部存储的就是自己所引用数组在堆空间中的首地址。

变量a,b,arr的内存分布可用下图进行简单表示:


从图中可以发现,引用变量并不直接存储对象本身,可以简单理解成存储的是对象在堆中空间的起始地址。通过该地址,引用变量便可以去操作对象。有点类似C语言中的指针,但是Java中引用要比指针的操作更简单。

2.4 Java 中的 null

在Java中,null 是一个特殊的值,表示一个引用类型变量没有引用任何对象。它是一个关键字,可以用来将引用类型变量初始化为一个空值。

当一个引用类型变量被赋值为 null,它表示该变量不引用任何对象,即它不指向任何有效的内存地址。这意味着该变量不能访问该对象的实例变量或调用对象的方法,因为它没有实际的对象引用。

使用 null 有几种常见的情况:

  1. 在声明一个引用类型变量时,如果还没有具体的对象要赋值给它,可以将其初始化为 null
int[] arr = null;
  1. 当需要释放一个对象的引用时,可以将该引用赋值为 null。这样,对象就不再被引用,有助于垃圾回收器判断该对象是否可以被回收。
arr = null;

需要注意以下几点:

  • null 只能被赋值给引用类型变量,不能赋值给基本类型变量,因为基本类型变量不是对象。
  • 当尝试使用一个值为 null 的引用类型变量进行实例变量访问或方法调用时,会导致空指针异常(NullPointerException)。因此,在使用引用类型变量之前,需要进行非空检查,以避免空指针异常的发生。
arr[0] = 1; //空指针异常

使用 null 可以帮助我们处理对象的缺失或无效引用的情况,但需要小心使用,以避免空指针异常。

三、数组的应用

3.1 保存数据

数组经常用于保存一组相关的数据。例如,一个学生成绩表可以使用数组来存储每个学生的成绩,一个商品库存列表可以使用数组来存储每个商品的库存数量。

int[] scores = {85, 90, 78, 92, 88}; // 学生成绩数组
int[] inventory = {10, 5, 20, 15}; // 商品库存数组

3.2 函数参数

数组可以作为函数的参数传递,以便在函数中操作和处理数组数据。例如,一个函数可以接受一个整数数组并计算数组中所有元素的总和。

public static int calculateSum(int[] numbers) {int sum = 0;for (int i = 0; i < numbers.length; i++) {sum += numbers[i];}return sum;
}int[] numbers = {1, 2, 3, 4, 5};
int sum = calculateSum(numbers); // 调用函数计算数组元素的总和
System.out.println("数组元素的总和为: " + sum);

3.3 函数返回值

数组也可以作为函数的返回值,用于返回多个相关的值。例如,一个函数可以返回一个包含某个范围内的所有偶数的数组。

public static int[] getEvenNumbers(int start, int end) {int size = (end - start) / 2 + 1;int[] evenNumbers = new int[size];int index = 0;for (int i = start; i <= end; i++) {if (i % 2 == 0) {evenNumbers[index] = i;index++;}}return evenNumbers;
}int[] evenNumbers = getEvenNumbers(1, 10); // 调用函数获取范围内的所有偶数
System.out.println("范围内的偶数数组: " + Arrays.toString(evenNumbers));

相关文章:

【Java】数组详解

文章目录 一、数组的基本认识1.1 数组的概念1.2数组的创建与初始化1.3 数组的使用 二、数组的类型 — 引用类型2.1 JVM 内存分布2.2 什么是引用类型2.3 基本类型变量与引用类型变量的区别2.4 Java 中的 null 三、数组的应用3.1 保存数据3.2 函数参数3.3 函数返回值 一、数组的基…...

NumPy库的学习

本文主要记录的是笔者在B站自学Numpy库的学习笔记。 引入numpy库 import numpy as np矩阵的创建 创建一个二行三列的矩阵。 array np.array([[1,2,3],[2,3,4]])查看array的行数、形状、元素数量 print("number of dim:",array.ndim) print("shape:"…...

CentOS安装IRIS

最近电脑提搞了&#xff0c;可以无顾虑创建虚拟机了&#xff0c;试一下在Linux安装IRIS&#xff0c;适用CentOS7.6上安装Intersystem公司的IRIS数据库&#xff0c;资料基本是空白&#xff0c;分享一下。 首先安装解压软件unzip和libicu&#xff0c;最小化安装的缺&#xff0c;…...

华为OD机试真题 JavaScript 实现【最多几个直角三角形】【2023Q1 100分】

一、题目描述 有 N 条线段&#xff0c;长度分别为 a[1]-a[n]。 现要求你计算这 N 条线段最多可以组合成几个直角三角形&#xff0c;每条线段只能使用一次&#xff0c;每个三角形包含三条线段。 二、输入描述 第一行输入一个正整数 T (1< T< 100) &#xff0c;表示有…...

vue3中的reactive、ref、toRef和toRefs

目录 reactivereactive的实现原理使用reactive的注意事项 refref的实现原理使用ref的注意事项 toRef和toRefsref和reactive的使用比较 reactive reactive用于创建响应式对象&#xff0c;它返回一个对象的响应式代理。即&#xff1a;它返回的对象以及其中嵌套的对象都会通过 Pr…...

数字图像处理与Python实现-图像增强经典算法汇总

图像增强经典算法汇总 文章目录 图像增强经典算法汇总1、像素变换2、图像逆变换3、幂律变换4、对数变换5、图像均衡化6、对比度受限自适应直方图均衡(CLAHE)7、对比度拉伸8、Sigmoid校正9、局部对比度归一化10、总结本文将对图像增强经典算法做一个简单的汇总。图像增强的经典…...

tag提示词总结

顺序的权重 越靠前的tag权重越大&#xff0c;越靠后的tag权重越小经验来讲&#xff0c;将图像质量相关的tag放在前面&#xff0c;例如masterpiece&#xff0c;best quality等&#xff1b;接着添加主体画风等&#xff1b;最后添加一些不太重要的细节 权重增减 (tag)&#xff1a…...

微信小程序原生开发功能合集二十:导航栏、tabbar自定义及分包功能介绍

本章实现导航栏及tabbar的自定义处理的相关方法介绍及效果展示。   另外还提供小程序开发基础知识讲解课程,包括小程序开发基础知识、组件封装、常用接口组件使用及常用功能实现等内容,具体如下:    1. CSDN课程: https://edu.csdn.net/course/detail/37977    2. 5…...

高通 Camera HAL3:项目开发技术点总结

做高通 Camera HAL3开发的一些技术点的总结、整理。 做个记录&#xff0c;方便后续查阅。 1.目录、so、配置文件 productName是项目名 out Target路径&#xff1a;\out\target\product\productName\chi-cdk&#xff1a;\vendor\qcom\proprietary\chi-cdk\ldc node&#xff1…...

chatgpt赋能python:Python怎么删除列表中的最大值和最小值

Python怎么删除列表中的最大值和最小值 在Python中&#xff0c;一个列表&#xff08;List&#xff09;是一种非常常见的数据结构&#xff0c;它允许我们以有序的方式存储和访问数据。但是&#xff0c;有时候我们需要从列表中删除最大或最小的值&#xff0c;以满足我们的特定需…...

简述Vue的生命周期以及每个阶段做的事情

03_简述Vue的生命周期以及每个阶段做的事情 思路 给出概念 列举出生命周期各个阶段 阐述整体流程 结合实际 扩展&#xff1a;vue3变化 回答范例 每个vue组件实例被创建后都会经过一系列步骤。比如它需要数据观测、模板编译、挂载实例到dom、以及数据变化的时候更新dom、…...

LeetCode-C#-0004.寻找两个正序数组的中位数

0.声明 该题目来源于LeetCode 如有侵权&#xff0c;立马删除。 解法不唯一&#xff0c;如有新解法可一同讨论。 1.题目 0004寻找两个正序数组的中位数 给定两个大小分别为m和n的正序&#xff08;从小到大&#xff09;数组nums1和nums2。 请你找出并返回着两个正序数组的中位…...

Vue.js 中的 $emit 和 $on 方法有什么区别?

Vue.js 中的 $emit 和 $on 方法有什么区别&#xff1f; 在 Vue.js 中&#xff0c;$emit 和 $on 方法是两个常用的方法&#xff0c;用于实现组件间的通信。它们可以让我们在一个组件中触发一个自定义事件&#xff0c;并在另一个组件中监听这个事件&#xff0c;从而实现组件间的…...

LAZADA平台的商品评论Python封装API接口接入文档和参数说明

LAZADA是一个位于东南亚的电商平台&#xff0c;成立于2012年。该平台覆盖的国家包括新加坡、马来西亚、印尼、菲律宾、泰国和越南等地。它提供了一个多样化的产品选择&#xff0c;包括时尚、美容、数码、母婴等商品&#xff0c;并且拥有许多知名品牌的官方旗舰店。同时&#xf…...

云原生Docker镜像管理

docker是什么&#xff1f; docker是一个go语言开发的应用容器引擎。 docker的作用&#xff1f; ①运行容器里的应用&#xff1b; ②docker是用来管理容器和镜像的一种工具。 #容器 与 虚拟机 的区别&#xff1f; 容器虚拟机所有容器共享宿主机内核每个虚拟机都有独立的操…...

ChatGPT+小红书的8种高级玩法

掌握了这套万能命令&#xff0c;让你快速做出小红书爆款文案! 一、用ChatGPT做定位 我是一个大龄的普通人&#xff0c;没有什么特殊的技能&#xff0c;接下来&#xff0c;请你作为一位小红书的账号定位专家&#xff0c;通过与我对话的方式&#xff0c;为我找到我的小红书账号定…...

shell脚本学习记录1(运算符)

Shell 传递参数 我们可以在执行 Shell 脚本时&#xff0c;向脚本传递参数&#xff0c;脚本内获取参数的格式为&#xff1a;$n。n 代表一个数字&#xff0c;1 为执行脚本的第一个参数&#xff0c;2 为执行脚本的第二个参数&#xff0c;以此类推…… 以下实例我们向脚本传递三个…...

vector 迭代器失效问题

vector 迭代器失效 迭代器的主要作用就是让算法能够不用关心底层数据结构&#xff0c;其底层实际就是一个指针&#xff0c;或者是对指针进行了封装&#xff0c;比如&#xff1a;vector的迭代器就是原生态指针T* 。因此迭代器失效&#xff0c;实际就是迭代器底层对应指针所指向…...

docker使用与服务器上的可视化(ROS rviz等)

1.安装docker 安装docker&#xff1a;官网教程&#xff0c;按照官网命令一步步来即可。 添加当前用户到docker用户组&#xff1a; 【docker】添加用户到docker组&#xff0c;这样后面运行docker的时候前面不需要加sudo命令&#xff0c;否则运行docker的时候一直需要在前面加su…...

最新版本Portraiture4.1中文版ps磨皮滤镜插件安装包

在Portraiture有非常强大的手动功能&#xff0c;可以为用户进行手动调整照片中的皮肤区域以达到更加完美的效果&#xff0c;软件还支持同时导入上千张照片&#xff0c;用户可以通过自动识别照片中的人脸从而依照自己的风格进行批量处理十分的方便快捷。 最新版本Portraiture 4…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

C#学习第29天:表达式树(Expression Trees)

目录 什么是表达式树&#xff1f; 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持&#xff1a; 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...