零基础学Java(4)

碎碎念:我勒个豆!写了这么多天才发现还有好多基础的知识居然没写!!!算了算了,以后如何需要的话再系统地写一遍吧,现在就想到哪写到哪......

关于print和printf

可变参数

参考文献可以放 3 篇、5 篇甚至 10 篇,格式统一只需要按顺序罗列;Java 的可变参数也一样,允许方法接收 “任意个数” 的同类型参数,不用提前定义参数个数,代码更灵活简洁。

语法格式

修饰符 返回值类型 方法名(参数类型... 参数名) { // 方法体 }
  • 关键符号:...(三个点,放在参数类型后、参数名前);
  • 注意事项:一个方法只能有一个可变参数,且必须放在参数列表的最后一位

实操案例

public class VarargsDemo { // 可变参数方法:接收任意个数的int类型参数(0个、1个、多个都可以) public static int sum(int... nums) { int total = 0; // 可变参数本质是数组,用普通for循环遍历即可 for (int num : nums) { // 增强for循环遍历(更简洁) total += num; } return total; } public static void main(String[] args) { // 调用可变参数方法:传入任意个数的参数 System.out.println(sum()); // 传入0个参数,输出0 System.out.println(sum(1)); // 传入1个参数,输出1 System.out.println(sum(1, 2)); // 传入2个参数,输出3 System.out.println(sum(1, 2, 3, 4, 5)); // 传入5个参数,输出15 } }

核心特性

1、本质是数组:编译器会自动把int... nums转为int[] nums,你可以像操作普通数组一样操作可变参数(比如通过nums.length获取参数个数):

public static int sum(int... nums) { System.out.println("传入的参数个数:" + nums.length); int total = 0; for (int i = 0; i < nums.length; i++) { // 普通for循环遍历 total += nums[i]; } return total; } 

2、参数灵活性

  • 可传入 0 个参数(此时nums是长度为 0 的空数组,不会报错);

可直接传入数组:和可变参数兼容,无需额外处理:

int[] arr = {1,2,3}; System.out.println(sum(arr)); // 直接传入数组,输出6 

3、优先级规则:当方法重载和可变参数方法同时存在时,编译器会优先调用 “精确匹配” 的普通方法,再调用可变参数方法:

// 普通方法(精确匹配2个int参数) public static int sum(int a, int b) { return a + b + 10; // 额外加10,便于区分 } // 可变参数方法 public static int sum(int... nums) { int total = 0; for (int num : nums) { total += num; } return total; } public static void main(String[] args) { System.out.println(sum(1, 2)); // 优先调用普通方法,输出13(不是3) System.out.println(sum(1, 2, 3)); // 无普通方法匹配,调用可变参数方法,输出6 }

递归

递归(Recursion)是 Java 中核心的编程思想之一,核心就是一个方法在其方法体内直接或间接调用自身,就像 “套娃” 一样,通过重复调用自身来拆解复杂问题,最终转化为简单的基础问题求解。

递归组成结构

  • 递归出口(终止条件):什么时候不调用自身方法。如果没有头,将陷入死循环。
  • 递归调用:什么时候需要调用自身方法。

实操案例(求 n 的阶乘)

阶乘定义:n! = n * (n-1) * (n-2) * ... * 11! = 10! = 1

public class RecursionDemo { // 递归方法求n的阶乘 public static int factorial(int n) { // 递归出口:n=0或n=1时,阶乘结果为1,停止递归 if (n == 0 || n == 1) { return 1; } // 递归调用:自身调用,将n!拆解为n * (n-1)! return n * factorial(n - 1); } public static void main(String[] args) { int result = factorial(5); // 计算5的阶乘 System.out.println("5! = " + result); // 输出120 } } 

执行流程拆解

factorial(5) → 5 * factorial(4) factorial(4) → 4 * factorial(3) factorial(3) → 3 * factorial(2) factorial(2) → 2 * factorial(1) factorial(1) → 1 (触发递归出口,停止调用,开始回溯) // 回溯计算结果:2*1=2 → 3*2=6 → 4*6=24 → 5*24=120

PS:在基数比较小的情况下用递归真的很简洁省事,但面对大基数问题(比如算10000的阶层)就会存在栈溢出等问题,说白了就是便利人类累死计算机......

数组

数组是 Java 中最基础的数据结构之一,核心是一组固定长度、存储相同数据类型的有序容器,一旦创建长度不可改变,就像一排大小一致的储物柜,每个柜子(下标)对应一个数据。

数组的核心特性

  1. 存储同类型数据:只能存放一种数据类型(如int[]只能存整数,String[]只能存字符串),不能混合存储;
  2. 固定长度:创建时必须指定长度,后续无法扩容或缩容;
  3. 有序排列:数据按下标(索引)存放,下标从0开始,最大下标为长度-1
  4. 内存连续分配:数组元素在内存中连续存放,访问效率高。

数组的创建与初始化

1. 静态初始化(已知具体元素,自动推导长度)

// 语法:数据类型[] 数组名 = {元素1, 元素2, ..., 元素n}; int[] numArr = {1, 2, 3, 4, 5}; // 整数数组 String[] nameArr = {"张三", "李四", "王五"}; // 字符串数组 

数组的申明有两种方式:int[ ] arr; 和 int arr[ ]; 两种方法的效果相同,但前者为首选方法,后者是C和C++语言风格的数组申明方式。

2. 动态初始化(未知具体元素,先指定长度)

// 语法:数据类型[] 数组名 = new 数据类型[长度]; int[] scoreArr = new int[3]; // 创建长度为3的整数数组,默认值为0 String[] addrArr = new String[2]; // 创建长度为2的字符串数组,默认值为null // 动态初始化后,手动赋值(通过下标赋值) scoreArr[0] = 85; scoreArr[1] = 90; scoreArr[2] = 78;

数组的访问与遍历

1. 单个元素访问

通过数组名[下标]访问,下标不能超出0 ~长度-1,否则抛出ArrayIndexOutOfBoundsException(数组下标越界异常)。

int[] numArr = {1, 2, 3, 4, 5}; System.out.println(numArr[0]); // 访问第1个元素,输出1 System.out.println(numArr[4]); // 访问最后1个元素,输出5 // System.out.println(numArr[5]); // 报错:下标越界(长度为5,最大下标为4) 

2. 数组遍历

int[] numArr = {1, 2, 3, 4, 5}; // 方式1:普通for循环(可操作下标,灵活控制遍历范围) for (int i = 0; i < numArr.length; i++) { // numArr.length 获取数组长度 System.out.print(numArr[i] + " "); // 输出:1 2 3 4 5 } System.out.println(); // 方式2:增强for循环(foreach,无需关注下标,仅遍历所有元素) for (int num : numArr) { System.out.print(num + " "); // 输出:1 2 3 4 5 }

对于方式2,我们在学习for循环时有提到过,所以重点可以了解一下方式1的“ .length”。

数组的常见操作

1. 求数组最大值

public static int getMax(int[] arr) { int max = arr[0]; // 假设第一个元素为最大值 for (int num : arr) { if (num > max) { max = num; // 更新最大值 } } return max; } 

2. 数组元素反转

public static void reverseArr(int[] arr) { for (int i = 0; i < arr.length / 2; i++) { // 交换 arr[i] 和 arr[arr.length-1-i] int temp = arr[i]; arr[i] = arr[arr.length - 1 - i]; arr[arr.length - 1 - i] = temp; } }

拓展

二维数组

在现阶段Java的学习中,多维数组的运用并不频繁,这里只是做个小小的拓展。

二维数组本质是 “数组的数组”,用于存储表格型数据(行 + 列)。

// 静态初始化 int[][] twoDArr = {{1, 2}, {3, 4}, {5, 6}}; // 访问元素:行下标 + 列下标 System.out.println(twoDArr[0][1]); // 输出2(第1行第2列) // 遍历二维数组 for (int i = 0; i < twoDArr.length; i++) { // 遍历行 for (int j = 0; j < twoDArr[i].length; j++) { // 遍历每行的列 System.out.print(twoDArr[i][j] + " "); } System.out.println(); }

Arrays 类

Java 中的 Arrays 类(位于 java.util 包下)是专门为数组提供便捷操作方法的工具类,它封装了大量数组相关的静态方法,能帮我们快速实现数组排序、查找、填充、比较、转换等功能。

以下以 int[] 数组为例,演示 Arrays 类的高频使用方法:

public class ArraysDemo { public static void main(String[] args) { int[] arr = {3, 1, 4, 1, 5, 9, 2, 6}; int[] arr2 = {3, 1, 4, 1, 5, 9, 2, 6}; int[] arr3 = new int[5]; // 1. 数组转字符串:直观打印数组内容(无需手动遍历) String arrStr = Arrays.toString(arr); System.out.println("数组原始内容:" + arrStr); // 输出:[3, 1, 4, 1, 5, 9, 2, 6] // 2. 数组排序:默认升序排序(快速排序算法) Arrays.sort(arr); System.out.println("排序后数组:" + Arrays.toString(arr)); // 输出:[1, 1, 2, 3, 4, 5, 6, 9] // 3. 二分查找:在**已排序**的数组中查找指定元素,返回下标;未找到返回负数 // 注意:必须先排序,否则查找结果无效 int index = Arrays.binarySearch(arr, 5); System.out.println("元素5在排序后数组中的下标:" + index); // 输出:5 // 4. 数组填充:将指定值填充到数组的所有位置 Arrays.fill(arr3, 10); System.out.println("填充后数组arr3:" + Arrays.toString(arr3)); // 输出:[10, 10, 10, 10, 10] // 5. 数组比较:判断两个数组的长度和对应位置元素是否完全一致 boolean isEqual = Arrays.equals(arr, arr2); System.out.println("arr和arr2是否相等:" + isEqual); // 输出:false(arr已排序,arr2未排序) // 6. 数组复制:复制指定长度的数组,比手动遍历复制更高效 // copyOf(原数组, 新数组长度):长度不足补默认值,超出截断 int[] arrCopy = Arrays.copyOf(arr, 6); System.out.println("复制后数组(长度6):" + Arrays.toString(arrCopy)); // 输出:[1, 1, 2, 3, 4, 5] } }

Read more

【工创赛2025-智能物流搬运塔吊方案视觉开源(2分15秒)】西安理工大学工程训练中心

【工创赛2025-智能物流搬运塔吊方案视觉开源(2分15秒)】西安理工大学工程训练中心

一、前言         本文也是我的第一篇ZEEKLOG博客,主要内容是记录一下2025年工训赛的参赛过程,讲解一下与louisaerdusai学长一起开发的智能物流视觉方案。主要内容为:实现函数、串口与下位机的通讯和整个实现流程,希望我们的经验能够帮助大家。         本文为视觉算法开源,其他部分开源请移步:【工创赛2025-塔吊结构方案开源(2分15秒)】西安理工大学工程训练中心-ZEEKLOG博客 二、本届视觉设计由来         我在今年校赛阶段参加的是智能救援赛道,由于我们机械设计的过于复杂和一些其他原因,机械结构的反复修改,最终没有尽快实现视觉与机械结构联调,导致我们在校赛就遗憾出局。在校赛遗憾结束后,我有幸加入了学长的队伍,在重新了解了物流搬运的视觉流程后,发现使用Jetson Nano运行OpenCV算法算是更加灵活的选择。但是在省赛是我也发现很多队伍采用的OpenMV方案也可以流畅运行,就我使用这些微型视觉模块的经验来说,我推荐使用MaixCAM pro来实现简单的算法,但是不得不说OpenCV的算法实现是更加通用且灵活的,同时使用OpenCV算

By Ne0inhk
Python实现开源AI模型引入及测试全过程

Python实现开源AI模型引入及测试全过程

文章目录 * 摘要 * 1. 引言:开源AI生态系统概述 * 1.1 开源AI的发展现状 * 1.2 技术栈选择 * 1.3 项目目标 * 2. 环境配置与项目初始化 * 2.1 系统要求 * 2.2 创建虚拟环境 * 2.3 依赖管理文件 * 2.4 安装依赖 * 2.5 项目结构 * 3. 模型原理与架构解析 * 3.1 BERT模型原理 * 3.1.1 Transformer编码器架构 * 3.2 Hugging Face Transformers架构 * 4. 数据准备与预处理 * 4.1 数据集选择与加载

By Ne0inhk

如何快速解决GitHub访问难题:一站式Hosts同步方案

如何快速解决GitHub访问难题:一站式Hosts同步方案 【免费下载链接】fetch-github-hosts🌏 同步github的hosts工具,支持多平台的图形化和命令行,内置客户端和服务端两种模式~ | Synchronize GitHub hosts tool, support multi-platform graphical and command line, built-in client and server modes 项目地址: https://gitcode.com/gh_mirrors/fe/fetch-github-hosts 还在为GitHub页面加载缓慢、代码克隆失败而烦恼吗?作为全球最大的代码托管平台,GitHub的访问速度问题一直是开发者面临的共同挑战。今天介绍的fetch-github-hosts工具,正是为GitHub访问加速而设计的专业解决方案。 🔍 工具核心原理深度解析 传统的Hosts工具大多依赖第三方IP查询接口,而fetch-github-hosts采用了更加直接高效的设计理念。它通过项目自身的服务器直接获取github.c

By Ne0inhk
2026全网最热Claude Skills工具箱,GitHub上最受欢迎的7大Skills开源AI技能库

2026全网最热Claude Skills工具箱,GitHub上最受欢迎的7大Skills开源AI技能库

猫头虎AI开源福利|全网最热Claude Skills工具箱,GitHub上最受欢迎的7大Skills神器! 大家好,我是猫头虎 🐯最近AI圈有个词儿火得一塌糊涂——#Skills(技能)。 作为Claude生态的"外挂系统",#Skills能让你的AI Agent从"聊天机器人"进化成"专业打工仔"。今天本虎给大家扒一扒GitHub上最受欢迎的7大#Skills神器,全部开源免费,文末附直达 戳! ⚠️ 安全提醒:近期已有黑客利用第三方#Skills进行攻击的案例,强烈建议优先使用官方或自制#Skills!别担心,第一个工具就是官方出品的"元技能制造机",零代码也能DIY专属技能! 🛠️ 核心工具篇|官方出品,必属精品 文章目录 * 猫头虎AI开源福利|全网最热Claude Skills工具箱,GitHub上最受欢迎的7大Skills神器! * 🛠️ 核心工具篇|官方出品,必属精品 * 1️

By Ne0inhk