【Java篇】一法不变,万象归一:方法封装与递归的思想之道
文章目录
- Java 方法的使用:从基础到递归的全面解析
- 一、方法的概念及使用
- 1.1 什么是方法 (method)?
- 1.2 方法定义
- 1.3 方法调用的执行过程
- 1.4 实参和形参的关系
- 1.5 没有返回值的方法
- 二、方法重载
- 2.1 为什么需要方法重载
- 2.2 方法重载的概念
- 2.2.4 C++ 和 Java 的比较:
- 2.3 方法签名
- 2.3.1 方法签名中的一些特殊符号说明
- 三、递归
- 3.1 生活中的故事
- 3.2 递归的概念
- 3.3 递归执行过程分析
- 3.4 递归练习
- 3.4.1 示例1:按顺序打印一个数字的每一位
- 3.4.2 示例2:递归求 1 + 2 + 3 + ... + 10
- 3.4.3 示例3:求一个非负整数各位数字之和
- 3.4.4 示例4:递归求斐波那契数列的第 N 项
- 四、总结与展望
Java 方法的使用:从基础到递归的全面解析
💬 欢迎讨论:如果你在阅读过程中有任何疑问或想要进一步探讨的内容,欢迎在评论区留言!我们一起学习、一起成长。
👍 点赞、收藏与分享:如果你觉得这篇文章对你有帮助,记得点赞、收藏并分享给更多想了解 Java 编程的朋友!
🚀 继续学习之旅:今天,我们将深入探讨 Java 中的方法,包括如何定义、调用、重载和递归使用方法。这些是每个 Java 程序员必备的技能。
一、方法的概念及使用
1.1 什么是方法 (method)?
方法是组织代码的一种形式,它允许将重复性代码封装在一个单独的块中,从而实现模块化。Java 方法类似于 C 语言中的“函数”。它是解决多次使用相同代码的理想方式。通过方法,我们不仅可以提高代码的可重用性,还能提高代码的可维护性和可读性。
为什么使用方法:
- 减少代码冗余:当某段功能代码频繁出现时,我们可以将它封装成一个方法,在多个地方调用,避免重复编写相同的代码。
- 提高代码的模块化:代码分块后,使得程序结构更加清晰,每个方法可以专注于处理一项任务。
- 易于修改与维护:如果某段功能需要修改,我们只需在方法内部修改一次,而不需要修改每个调用该功能的地方。
示例:
假设我们需要开发一个日历程序,每年都会判断某个年份是否为闰年,如果每次都写相同的代码就显得非常繁琐且容易出错。我们可以将判断闰年的代码封装成一个方法:
public static boolean isLeapYear(int year) {if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {return true;}return false;
}
当需要判断某个年份是否为闰年时,直接调用该方法即可,而不需要每次都重新写相同的代码。
易错点:
- 方法的定义与函数的混淆:方法与函数在不同语言中有不同的含义。在 Java 中,所有方法都必须定义在类中,且必须通过类的对象或静态类名调用,而函数则不依赖于类结构。
- 没有方法的好处:如果不使用方法,代码会变得冗长且难以维护。如果有多个地方需要使用相同代码,修改时必须在所有地方修改,不利于维护。
1.2 方法定义
方法的定义是编程中的基础,在 Java 中,每个方法都有特定的语法格式。方法定义的语法如下:
修饰符 返回值类型 方法名称(参数列表) {方法体代码;[return 返回值];
}
例子:定义一个判断闰年的方法
public static boolean isLeapYear(int year) {if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {return true;}return false;
}
解释:
- 修饰符:表示方法的访问权限和属性。在这里我们使用
public static
,意味着该方法是公有的,可以被外部访问,并且是静态的,可以不需要创建对象即可调用。 - 返回值类型:方法执行后返回的值的类型。在本例中是
boolean
类型,用来表示是否为闰年(true
或false
)。 - 方法名称:
isLeapYear
是方法的名称,通常采用小驼峰命名法。 - 参数列表:方法的输入参数,在本例中是一个
int
类型的参数year
,表示要判断的年份。 - 方法体:方法的实现代码,在本例中用于判断是否为闰年,并返回结果。
其他注意事项:
- 方法名必须唯一:同一个类中的方法名称不能重复,除非参数列表不同(方法重载)。
- 方法定义不能嵌套:方法定义不能写在另一个方法内部。
1.3 方法调用的执行过程
方法调用的过程包括以下步骤:
- 调用方法:当程序执行到方法调用语句时,控制流转到该方法,并开始执行该方法中的代码。
- 传递参数:在调用方法时,传递的实参值会被赋给方法的形参。这些参数可以是基本数据类型的值,也可以是对象。
- 执行方法体:方法体中的语句开始执行,按照代码顺序逐条执行。
- 返回值:如果方法有返回值,执行完成后会通过
return
返回计算结果。如果方法的返回类型是void
,则不返回任何值。
示例:调用方法计算两个整数的和:
public class MethodExample {public static void main(String[] args) {int a = 10;int b = 20;System.out.println("第一次调用方法之前");int result = add(a, b); // 调用方法System.out.println("第一次调用方法之后");System.out.println("result = " + result);}public static int add(int x, int y) {return x + y; // 执行方法体}
}
执行过程:
- 程序在
main
方法中调用add(a, b)
,此时控制转到add
方法。 add
方法接收a
和b
作为参数,执行相加操作,并返回计算结果。- 返回值
result
被赋值为30
,然后输出。
易错点:
- 方法调用的顺序问题:确保方法调用语句书写顺序正确,否则会导致
null
或错误的返回结果。 - 传递错误的参数类型:方法的形参与实参的类型要匹配,否则编译时会报错。
1.4 实参和形参的关系
在 Java 中,实参(实实际参数)是调用方法时传递给方法的参数值,而形参(形式参数)是在方法定义时指定的变量名,用来接收传递给方法的实参。
实参与形参的关系:
- 形参:方法定义时的变量,用于接收实参值。在方法调用时,形参是局部的,仅在方法内部有效。
- 实参:在调用方法时传递的实际值,可以是常量、变量或表达式。
例子:
public class TestMethod {public static void main(String[] args) {int result = fac(5); // 实参 5 被传递给形参 nSystem.out.println(result); // 输出阶乘结果}public static int fac(int n) {int result = 1;for (int i = 1; i <= n; i++) {result *= i;}return result;}
}
解释:
- 实参:
5
被传递给形参n
。 - 形参:
n
是fac
方法的局部变量,接收传递过来的实参。
易错点:
- 实参与形参类型不匹配:确保方法调用时传递的实参类型与方法定义时的形参类型匹配。否则,编译时会报错。
1.5 没有返回值的方法
在 Java 中,如果方法不需要返回值,则可以声明返回类型为 void
,表示该方法不返回任何值。
例子:
public class TestMethod {public static void main(String[] args) {int[] arr = {10, 20};swap(arr); // 调用没有返回值的方法System.out.println("arr[0] = " + arr[0] + " arr[1] = " + arr[1]); // 输出交换后的结果}public static void swap(int[] arr) {int tmp = arr[0];arr[0] = arr[1];arr[1] = tmp; // 交换数组元素}
}
解释:
swap
方法通过void
返回类型表示没有返回值。- 该方法交换了数组中的两个元素,直接通过数组的引用修改了数组的值。
易错点:
- 返回类型不一致:如果方法声明了
void
返回类型,必须确保方法内没有return
语句尝试返回值,否则编译时会出错。
二、方法重载
2.1 为什么需要方法重载
方法重载是 Java 中的一个非常有用的特性。它允许我们定义多个具有相同方法名,但参数列表不同的方法。在一些情况下,可能会遇到需要多个方法来执行相似任务但参数不同的情况。通过方法重载,我们可以使用相同的方法名来执行不同的操作,避免了为每个不同的情况都起个新方法名。
示例:不同参数类型的相加方法
public static int add(int x, int y) {return x + y; // 用于加法操作,两个整数相加
}public static double add(double x, double y) {return x + y; // 用于加法操作,两个浮点数相加
}
这里,add
方法重载了两次:一次接受两个整数,另一次接受两个浮点数。虽然它们的操作是相同的(加法),但由于参数的不同,Java 允许使用相同的名称调用不同版本的 add
方法。
为什么要重载:
- 简化代码:避免多个方法使用不同的名称来处理相似的任务,使代码更简洁易懂。
- 提高可维护性:方法名称统一,修改和维护更容易。如果参数变化,不需要修改多个方法名称。
- 增强灵活性:能够处理不同类型和数量的参数,而不需要为每个变种写不同的代码。
易错点:
- 过度重载:方法重载有时会使代码变得复杂,尤其是当方法名相同但参数差异较小的时候,可能导致程序员难以理解哪个方法会被调用,尤其是在多次重载的情况下。
2.2 方法重载的概念
方法重载(Method Overloading)是指在同一个类中,多个方法具有相同的名字,但它们的参数列表不同(参数的数量、类型、顺序可以不同)。方法重载和方法的返回值类型无关,不能仅仅根据返回类型来区分不同的方法。
方法重载的规则:
- 方法名必须相同:所有重载的方法必须使用相同的方法名。
- 参数列表必须不同:重载的方法必须有不同的参数列表。可以通过参数的数量、类型或顺序来区分。
- 返回类型无关:返回类型不能作为重载的方法区分标准。
示例:参数数量不同的重载:
public static int add(int x, int y) {return x + y;
}public static int add(int x, int y, int z) {return x + y + z;
}
在这个例子中,add
方法根据传入参数的数量不同进行了重载。第一个方法接受两个整数,第二个方法接受三个整数。
易错点:
- 仅根据返回类型重载:方法重载不能仅仅根据返回类型不同来区分。例如,如果两个方法只有返回类型不同,它们不能被视为重载方法,会导致编译错误。
// 错误示例:仅凭返回类型不同无法重载
public static int add(int x, int y) {return x + y;
}public static double add(int x, int y) { // 编译错误:方法已定义,无法仅凭返回类型重载return x + y;
}
2.2.4 C++ 和 Java 的比较:
-
C++:允许通过 返回类型的不同 来进行方法重载,即使方法的参数完全相同,C++ 编译器也不会报错,它会将方法的返回类型作为重载的一部分来区分方法。但这种做法在运行时可能会引发问题,因为编译器不能根据返回类型来明确选择调用哪个方法。
-
Java:严格要求方法重载必须基于 参数列表的不同,返回类型不能作为重载的依据。如果两个方法的参数列表相同但返回类型不同,Java 编译器会在编译时直接报错,提示方法冲突。
例子比较:
Java 中的错误示例:
public class Test {public static int add(int x, int y) {return x + y;}public static double add(int x, int y) { // 编译错误:方法已定义,无法仅凭返回类型重载return x + y;}public static void main(String[] args) {System.out.println(add(5, 10));}
}
- 错误解释:在 Java 中,这会引发编译错误,提示
add(int, int)
方法已经定义,不能仅凭返回类型来重载方法。
C++ 中的示例:
int add(int x, int y) {return x + y;
}double add(int x, int y) { // C++ 允许通过返回类型不同来重载return x + y;
}int main() {int result1 = add(5, 10); // 调用第一个方法double result2 = add(5, 10); // 调用第二个方法cout << result1 << endl;cout << result2 << endl;return 0;
}
- C++ 行为:C++ 编译器允许这种返回类型不同的重载,尽管这样做在实践中可能会引发混淆,但 C++ 编译时不会报错。
总结:
-
Java:方法重载必须依据参数列表的差异,而 返回类型不同不会导致重载。这种严格的规则有助于提高代码的可读性和可维护性,避免调用时的混淆。
-
C++:返回类型不同也可作为重载的依据,但这种做法容易造成调用时的歧义,并且不推荐使用。
2.3 方法签名
在同一个作用域中不能定义两个相同名称的方法。比如:方法中不能定义两个名字符合相同的变量,那么为什么类中就可以定义方法名相同的方法呢?这是因为 方法签名 是根据方法的 完整路径名+参数列表+返回类型 来确定的。
具体方式是:方法全路径名+参数列表+返回类型构成方法完全的名称。
示例:
public class TestMethod {public static int add(int x, int y) {return x + y;}public static double add(double x, double y) {return x + y;}public static void main(String[] args) {add(1, 2);add(1.5, 2.5);}
}
在上面的代码中,我们定义了两个 add
方法,分别接受 int
和 double
类型的参数。虽然方法名称相同,但它们的方法签名不同,因为它们的 参数类型不同。
2.3.1 方法签名中的一些特殊符号说明
在方法签名中,某些符号代表了不同的数据类型或含义,具体如下:
特殊字符 | 数据类型 |
---|---|
V | void |
Z | boolean |
B | byte |
C | char |
S | short |
I | int |
J | long |
F | float |
D | double |
[ | 数组(以左括号开始,配合其他的特殊字符,表示对应数据类型的数组,几个[表示几维数组) |
L | 引用类型(以L开头,以;结尾,表示引用类型的全类名) |
示例说明:
对于方法签名中的特殊字符:
- V 表示方法没有返回值(
void
)。 - I 表示
int
类型。 - D 表示
double
类型。 - L 表示引用类型,以
L
开头并以;
结尾,例如:Ljava/lang/String;
表示String
类型。 - [ 表示数组类型,例如
I[]
表示int
类型的数组。
通过这些符号,Java 可以精确地标识一个方法。
三、递归
3.1 生活中的故事
从前有座山,山上有座庙,庙里有个老和尚给小和尚讲故事,故事内容是这样的:
“从前有座山,山上有座庙,庙里有个老和尚给小和尚讲故事,讲的就是:
“从前有座山,山上有座庙…”
“从前有座山……””
这个故事有个特征:故事中包含了自身。正因为如此,当我们遇到问题时,可以尝试将大问题拆分为与原问题结构相同的子问题,待子问题解决后,整体问题也就迎刃而解了。
3.2 递归的概念
在编程中,递归指的是一个方法在执行过程中调用自身。这种思想类似于数学中的“数学归纳法”,通常包含两个部分:
- 递归出口:例如求阶乘时,当 N = 1 时返回 1,这就是递归结束的条件。
- 递归公式:将原问题转换为对较小规模问题的求解,比如 N! 可转换为 N * (N-1)!。
递归的必要条件有:
- 子问题与原问题解法一致:将原问题拆分成结构相似的子问题。
- 明确的递归出口:防止无限递归,保证问题最终能求解。
代码示例:递归求 N 的阶乘
public static int factor(int n) {if (n == 1) { // 递归出口return 1;}return n * factor(n - 1); // 递归调用自身
}public static void main(String[] args) {int n = 5;int ret = factor(n);System.out.println("ret = " + ret); // 输出 ret = 120
}
3.3 递归执行过程分析
理解递归关键在于清楚地了解方法的执行过程。当一个方法调用自身时,每次调用都会在调用栈中创建一个新的“栈帧”,保存本次调用的参数和返回地址。方法执行结束后,会依次返回到上层调用位置继续执行。
代码示例:带调用过程打印的阶乘求解
public static int factor(int n) {System.out.println("函数开始, n = " + n);if (n == 1) {System.out.println("函数结束, n = 1 ret = 1");return 1;}int ret = n * factor(n - 1);System.out.println("函数结束, n = " + n + " ret = " + ret);return ret;
}public static void main(String[] args) {int n = 5;int ret = factor(n);System.out.println("ret = " + ret);
}
执行结果示例:
函数开始, n = 5
函数开始, n = 4
函数开始, n = 3
函数开始, n = 2
函数开始, n = 1
函数结束, n = 1 ret = 1
函数结束, n = 2 ret = 2
函数结束, n = 3 ret = 6
函数结束, n = 4 ret = 24
函数结束, n = 5 ret = 120
ret = 120
关于 “调用栈”
方法调用的时候, 会有一个 “栈” 这样的内存空间描述当前的调用关系. 称为调用栈.
每一次的方法调用就称为一个 “栈帧”, 每个栈帧中包含了这次调用的参数是哪些, 返回到哪里继续执行等信息.
后面我们借助 IDEA 很容易看到调用栈的内容
3.4 递归练习
以下是几个递归练习示例,帮助你巩固递归思想:
3.4.1 示例1:按顺序打印一个数字的每一位
例如,对于数字 1234,依次打印出 1 2 3 4
。
public static void print(int num) {if (num > 9) {print(num / 10);}System.out.println(num % 10);
}
3.4.2 示例2:递归求 1 + 2 + 3 + … + 10
public static int sumSeries(int n) {if (n == 1) {return 1;}return n + sumSeries(n - 1);
}
3.4.3 示例3:求一个非负整数各位数字之和
例如,输入 1729,返回 1 + 7 + 2 + 9 = 19。
public static int sumDigits(int num) {if (num < 10) {return num;}return num % 10 + sumDigits(num / 10);
}
3.4.4 示例4:递归求斐波那契数列的第 N 项
斐波那契数列介绍
斐波那契数列定义为:
fib(1) = 1
fib(2) = 1
- 对于 n > 2,
fib(n) = fib(n - 1) + fib(n - 2)
递归实现:
public static int fib(int n) {if (n == 1 || n == 2) {return 1;}return fib(n - 1) + fib(n - 2);
}
由于递归计算斐波那契数列时存在大量重复运算,当 n 较大时(如 fib(40)),执行速度会非常慢。为此,我们可以采用循环方式优化:
循环实现(优化版):
public static int fibOptimized(int n) {if (n == 1 || n == 2) {return 1;}int last2 = 1;int last1 = 1;int cur = 0;for (int i = 3; i <= n; i++) {cur = last1 + last2;last2 = last1;last1 = cur;}return cur;
}
四、总结与展望
本文详细介绍了Java方法的基本概念、重载以及递归应用,结合实际代码示例,帮助读者理解方法在Java编程中的重要作用。我们看到,相较于其他语言,Java通过方法的封装与重载提供了更高的灵活性和代码重用性。在递归的部分,文章阐述了递归实现的原理及其优势,同时提醒在使用递归时要注意栈溢出等问题。掌握这些方法相关的技巧后,读者将能更高效地编写清晰、可维护的Java代码。
未来,我们将继续探讨Java中的其他高级话题,如多线程编程、网络通信等,帮助读者进一步提升编程技能。如果你有任何疑问或建议,欢迎在评论区留言,让我们一起成长、一起进步!
以上就是关于【Java篇】一法不变,万象归一:方法封装与递归的思想之道内容啦,各位大佬有什么问题欢迎在评论区指正,或者私信我也是可以的啦,您的支持是我创作的最大动力!❤️
相关文章:
【Java篇】一法不变,万象归一:方法封装与递归的思想之道
文章目录 Java 方法的使用:从基础到递归的全面解析一、方法的概念及使用1.1 什么是方法 (method)?1.2 方法定义1.3 方法调用的执行过程1.4 实参和形参的关系1.5 没有返回值的方法 二、方法重载2.1 为什么需要方法重载2.2 方法重载的概念2.2.4 C 和 Java 的比较&…...
SpringBoot解决跨域
将这个类添加到项目中 ResponseAdvice.java package com.example.homeLearn.config;import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.server.ServerHttpRequest; import org.springframework…...
【实战ES】实战 Elasticsearch:快速上手与深度实践-附录-2-性能调优工具箱
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 附录-性能调优工具箱 2-Elasticsearch 性能调优工具箱深度指南一、性能诊断工具集1.1 实时监控工具1.2 慢查询分析 二、硬件与基础架构优化2.1 存储方案选型2.2 JVM调优参数 三、索引…...
UDP协议栈之整体架构处理
在之前的章节中,笔者就UDP、ICMP、IP、ARP、MAC层的报文格式,以及组帧解帧、CRC校验、分片处理等操作进行了具体介绍以及详细代码实现,并且通过了仿真测试。但之前的仿真测试都是对单层报文的组帧解帧进行的,这些模块仍处于“孤立…...
健康医疗:动态代理 IP 保障医疗数据安全,提升远程医疗服务质量!
在数字化浪潮的推动下,远程医疗服务以其便捷性和高效性受到了广泛的关注。然而,随之而来的是数据安全问题,尤其是医疗数据的安全性,成为了制约远程医疗服务发展的关键因素。幸运的是,动态代理IP技术的出现,…...
Navicat SqlServer 设置自增主键
Navicat是一款优秀的数据库管理工具,可以连接很多类型的数据库。使用它可以极大的提高工作效率。 Navicat 不能设置SqlServer自增字段,只能通过sql语句来实现 建表时设置 create table <表名> ( <字段1-主键> int identity (1,1) primar…...
实验8 搜索技术
实验8 搜索技术 一、实验目的 (1)掌握搜索技术的相关理论,能根据实际情况选取合适的搜索方法; (2)进一步熟悉盲目搜索技术,掌握其在搜索过程中的优缺点; (3)…...
IMA+DeepSeekR1+本地知识库撰写NOIP2008普及组T3【传球游戏】题解
目录 一、提问词 二、DeepSeekR1回复 题目描述 解题思路 实现代码 代码说明 三、说明 【IMADeepSeekR1本地知识库】撰写NOIP2008普及组复赛题解系列 1、IMADeepSeekR1本地知识库撰写NOIP2008普及组T1【ISBN 号码】题解-CSDN博客 2、IMADeepSeekR1本地知识库撰写NOIP200…...
查找特定的值(信息学奥赛一本通-1110)
【题目描述】 在一个序列(下标从1开始)中查找一个给定的值,输出第一次出现的位置。 【输入】 第一行包含一个正整数n,表示序列中元素个数。1 <n< 10000。 第二行包含n个整数,依次给出序列的每个元素,相邻两个整数之间用单个…...
Qt项目中集成第三方模块的.pri文件
对于功能模块较多的Qt项目,使用pri文件管理模块文件,降低工程复杂度,提高软件模块的封装性和重用性。 一、.pro与.pri 对于模块化编程,Qt提供了pro和pri,pro管理项目,pri管理模块。 .pro 文件是Qt项目的…...
200多种算法应用于二维和三维无线传感器网络(WSN)覆盖场景
2.1 二元感知模型 在当前无线传感器网络(WSN)覆盖场景中,最常见且理想的感知模型是二元感知模型[27]。如图2所示, Q 1 Q_1 Q1和 Q 2 Q_2 Q2代表平面区域内的两个随机点。 Q 1 Q_1 Q1位于传感器的检测区域内,其感…...
【QT】文件系统相关 -- QFile
一、Qt 文件概述 🔥 文件操作是应用程序必不可少的部分。Qt 作为⼀个通用开发库,提供了跨平台的文件操作能力。Qt 提供了很多关于⽂件的类,通过这些类能够对文件系统进行操作,如文件读写、文件信息获取、文件制或重命名等 二、输…...
transformer bert 多头自注意力
输入的(a1,a2,a3,a4)是最终嵌入,是一个(512,768)的矩阵;而a1是一个token,尺寸是768 a1通过Wq权重矩阵,经过全连接变换得到查询向量q1;a2通过Wk权重矩阵得到键向量k2;q和k点乘就是值…...
人工智能之数学基础:线性变换的象空间和零空间
本文重点 前面的课程中,我们学习了线性变换,由此而引申出线性变换的象空间和零空间,这两个空间在机器学习领域会被经常用到,本文对此进行学习。 直观理解 总的来说象空间就是经过线性变换得到的空间,零空间就是经过线性变换是零的元素构成的空间。 从几何角度来看,象空…...
数据的存储---整型、浮点型
目录 一、整型在内存中的存储 1. 原码、反码、补码 2. 大端与小端 二、浮点数在内存中的存储 1.浮点数的存 2. 浮点数的取 3. 题目解析 一个变量的创建需要在内存中开辟空间,而开辟的空间大小是由数据类型决定的。下面我们就来讨论一下整型、浮点型在内存中的…...
鲸鱼算法WOA对风电场风电机组一次二次调频参数进行全局最优辨识,二次调频参数辩识matlab/simulink,也可进一步修改成一次调频参数辩识
模型为二次调频模型,也可修改为一次调频模型参数辩识 随着风电在电力系统中占比提高,其调频特性对电力系统频率稳定性的影响增大,例如,随着风电渗透水平不断提升,系统惯量不断增加,电力系统频率不断下降,在…...
Spring 中 SmartInitializingSingleton 的作用和示例
一、 接口定义 SmartInitializingSingleton 是 Spring 框架提供的一个 单例 Bean 全局初始化回调接口,用于在 所有非延迟单例 Bean 初始化完成后 执行自定义逻辑。 核心方法: public interface SmartInitializingSingleton {void afterSingletonsInsta…...
《TCP/IP网络编程》学习笔记 | Chapter 18:多线程服务器端的实现
《TCP/IP网络编程》学习笔记 | Chapter 18:多线程服务器端的实现 《TCP/IP网络编程》学习笔记 | Chapter 18:多线程服务器端的实现线程的概念引入线程的背景线程与进程的区别 线程创建与运行pthread_createpthread_join可在临界区内调用的函数工作&#…...
Unity AI 技术浅析(三):智能代理(Agents)
Unity AI的智能代理(Agents)技术是实现游戏和虚拟现实应用中非玩家角色(NPC)、敌人、盟友等智能行为的核心。通过智能代理,开发者可以为虚拟角色赋予感知、决策和行动的能力,使其能够与环境和其他角色进行复杂的交互。 一、智能代理的基本原理 智能代理是能够在特定环境…...
加油站~~
求最少加油次数就是一个贪心问题,这里也不需要证明,根据我们的常识也知道就是走到油不够的时候就加油就好了,这里的no solution这有在两个加油站之间的距离大于了加满油后的行驶距离才会存在,其他情况都是可以计算的。代码有很多细…...
【商城实战(24)】商城性能大揭秘:压力测试与性能监控实战
【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配…...
Linly-Talker:开源数字人框架的技术解析与影响
一、引言:AI 数字人的发展趋势 近年来,数字人(Digital Human) 技术迅速发展,从最早的 2D 虚拟主播,到如今能够进行实时交互的 3D 智能助手,AI 在多模态交互领域的应用愈发广泛。各大互联网公司…...
【Nexus】Maven 私服搭建以及上传自己的Jar包
Nexus 安装 docker run -d -uroot --name nexus3 --restartalways -p 8081:8081 -v /data/nexus-data/blobs:/nexus-data/blobs -v /etc/localtime:/etc/localtime sonatype/nexus3这里也提供一下docker-composer的方法 .env 文件 VERSIONlatest CONTAINER_NAMECONTAINER_N…...
wlwrap 与 rlwrap 的区别对比:图形显示协议的演变
在 Linux 系统中,许多工具和程序依赖于命令行界面(CLI)来进行交互,尤其是对于那些没有图形用户界面的应用程序。在这种情况下,命令行编辑、历史记录和自动补全等功能是提升工作效率和用户体验的关键。rlwrap 和 wlwrap…...
矩阵交换行(信息学奥赛一本通-1119)
【题目描述】 给定一个55的矩阵(数学上,一个rc的矩阵是一个由r行c列元素排列成的矩形阵列),将第n行和第m行交换,输出交换后的结果。 【输入】 输入共6行,前5行为矩阵的每一行元素,元素与元素之间以一个空格分开。 第6行包含两个整…...
CP210x 驱动秘籍:打通 Windows 11 端口的任督二脉
前言 江湖上,众多电脑侠客在安装 Windows 11 时,遭遇“端口失踪案”。原来,这是缺少 CP210x 驱动的“内功心法”。今日,贫道便传授一套独门秘籍,助你打通端口“任督二脉”,让数据流畅如江湖中轻功高手。 …...
IDEA集成git,项目的克隆,远程仓库中文件的添加删除
目录 一、克隆项目 二、使用IDEA完成文件的上传和删除 1.配置git 2.上传 3.删除(通过git bash) 一、克隆项目 点击克隆,复制url ,如下 打开你想要克隆到哪里,右击,选择 open Git Bash here 这一步之后…...
分治构造格雷码
题目描述 格雷码是一种二进制编码方式,其特性是任意两个相邻的码只有一位二进制位不同。给定一个整数 n,表示格雷码的位数,请生成所有 n 位格雷码,并按照格雷码的标准顺序输出。 输入格式 输出样例输入包含一个整数 n,…...
区跨链知识和概念
1、以太坊 Geth 源码解析 Geth(Go Ethereum)是以太坊官方提供的 Go 语言实现的客户端,广泛用于以太坊全节点运行、挖矿、DApp 开发等。理解 Geth 的源码有助于掌握以太坊区块链底层逻辑,如区块同步、EVM 执行、P2P 交互等。 2、…...
C# net deepseek RAG AI开发 全流程 介绍
deepseek本地部署教程及net开发对接 步骤详解:安装教程及net开发对接全流程介绍 DeepSeekRAG 中的 RAG,全称是 Retrieval-Augmented Generation(检索增强生成),是一种结合外部知识库检索与大模型生成能力的技术架构。其…...
REST 请求返回 Invalid Credentials
REST 请求返回 “Invalid Credentials”(无效凭据),通常表示身份验证失败。可能的原因和解决方案如下: 可能的原因 & 解决方案 用户名或密码错误 确保使用正确的用户名和密码。如果 API 需要 Base64 编码的 Authorization 头…...
方案推介:206页WORD版ERP系统软件投标书整体解决方案
(推介资料包含于绑定资源内) 该文档是一份 ERP 系统软件投标书,围绕ERP 系统展开,全面阐述了其为机械加工企业提供的整体解决方案、应用价值、行业成功案例及标准功能,旨在助力企业实现信息化管理升级 。 ERP 软件系统…...
WebSocket生命周期和vue中使用
ing。。。晚点更新 进入页面,生命周期挂载后,window监听ws连接online 正常情况,心跳包检测避免断开 非正常情况,ws.onclose断开, 判断1000状态吗,触发重连函数。 定时器,重连,判断…...
RabbitMQ消息持久化与Lazy模式对比分析
RabbitMQ消息持久化与Lazy模式对比分析 在RabbitMQ中,消息持久化与Lazy模式是两种不同的机制,分别针对消息可靠性、存储优化等不同维度设计。以下从六个层面进行深度对比: 一、核心目标与作用对象差异 维度消息持久化(delivery_…...
Springboot中的异常处理
ControllerAdvice虽然只是在处理Controller注解的类,在Service层抛出的异常如果没有在Service层被处理的话,会向上抛出到到Controller层,再被异常处理器捕获 1. 全局异常处理 ControllerAdvice:全局处理器,处理有Con…...
深入解析Go语言Channel:源码剖析与并发读写机制
文章目录 Channel的内部结构Channel的创建过程有缓冲Channel的并发读写机制同时读写的可能性发送操作的实现接收操作的实现 并发读写的核心机制解析互斥锁保护环形缓冲区等待队列直接传递优化Goroutine调度 实例分析:有缓冲Channel的并发读写性能优化与最佳实践缓冲…...
C++中虚析构函数的作用是什么?为什么基类需要虚析构函数?
C中虚析构函数的作用是什么?为什么基类需要虚析构函数? 在C中,虚析构函数(virtual destructor)的作用是确保在通过基类指针或引用删除派生类对象时,能够正确调用派生类的析构函数,从而避免资源…...
ClickHouse合并任务与查询延迟专项测试
ClickHouse合并任务与查询延迟专项测试 1. 测试目的 验证周期性高延迟(~900ms)是否由后台合并任务(Merge)引起。 2. 测试环境 组件配置ClickHouse版本24.8.3.13服务器硬件8核CPU / 32GB内存 / NVMe SSD测试表log_test 3. 测试…...
3.14学习总结
今天完成了几道关于二叉树的算法题 关于二叉树的最小最大深度和数据流中的第k大元素,用到优先队列,学习了有关java的基础知识,学习了双指针法。...
OpenHarmony自定义子系统、部件与模块
如图所示,OpenHarmony系统源码中,大体上按照不同种类的功能分成多个子系统,然后一个子系统内部进一步在同类功能上的差异性划分成一个或多个部件,也就是说一个部件表示一个具体功能的源码集合。最后一个部件的源码再划分成一个或多…...
PPT 相关资料介绍
文章目录 一、iSlide 工具二、免费 PPT 模板下载三、Kimi 一键生成 PPT 一、iSlide 工具 iSlide 官网 二、免费 PPT 模板下载 7个完全免费的PPT模板下载网站 优品PPT 第一PPT 三、Kimi 一键生成 PPT ☆...
C# 发送邮件 报错:此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站。
C# 发送邮件 报错:此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站。 报错信息分析 当你遇到如下报错时: 此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站。…...
大数据-spark3.5安装部署之standalone模式
真实工作中还是要将应用提交到集群中去执行,Standalone模式就是使用Spark自身节点运行的集群模式,体现了经典的master-slave模式。集群共三台机器,具体如下 u22server4spark: master worker u22server4spark2: worke…...
接口自动化入门 —— Jmeter实现在接口工具中关联接口处理方案
1. JMeter 接口关联处理的核心概念 接口关联是指在多个接口请求之间共享数据,例如将一个接口的返回值作为另一个接口的输入参数。常见的场景包括: 使用登录接口返回的 Token 作为后续接口的认证信息。 将一个接口返回的 ID 作为另一个接口的请求参数。…...
WebForms HTML:深入理解与高效运用
WebForms HTML:深入理解与高效运用 引言 随着互联网技术的飞速发展,WebForms HTML作为Web开发中的一种重要技术,已经成为了许多开发者日常工作中不可或缺的一部分。本文将深入探讨WebForms HTML的原理、应用场景以及高效运用技巧࿰…...
VSCode 搭建C++编程环境 2025新版图文安装教程(100%搭建成功,VSCode安装+C++环境搭建+运行测试+背景图设置)
名人说:博观而约取,厚积而薄发。——苏轼《稼说送张琥》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、VScode下载及安装二、安装 MinGW-w64 工具链三、Windows环境变量配置四、检查 M…...
【Linux 内核 | 操作系统 | 内核编译】内核编译中与锁调试相关的设置有哪一些?内核 Debug 选项中 LockDep 和其他锁调试选项详解
问题描述: 我在看内核锁调试的信息时,看到了一些内核编译参数相关的设置,开启这些信息可以帮助我们在测试环境中调试锁的竞争情况,可以详细的打印出来一些线程持有锁,一些线程争抢锁的信息。 以下是我的配置&#…...
LinuX---Shell---变量
系统预定义变量 常用系统变量 PATH、HOME、PWD、SHELL、USER等 获取变量的值 语法:$变量名 $和变量名之间不能有空格。 案例实操 查看系统变量的值 fengubuntu:~$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/u…...
深入理解Spring MVC:构建灵活的Web应用
大家好!今天我们来聊聊Spring框架中的一个重要模块——Spring MVC。Spring MVC是一个基于MVC(Model-View-Controller)架构的Web框架,它提供了强大的功能来处理HTTP请求、生成动态内容以及管理Web应用程序的流程。无论是构建RESTfu…...
详解SQL数据查询功能
数据查询 一、 单表查询1. 选择表中的若干列2. 选择表中的若干元组3. ORDER BY 子句4. 聚合函数5. GROUP BY 子句6. LIMIT 子句综合示例: 二、 多表查询1. 等值连接查询 (Equi-Join)2. 非等值连接查询 (Non-Equi Join)3. 自然连接查询 (Natural Join)4. 复合条件连接…...