目录
[1. 方法基础知识](#1. 方法基础知识)
[1.1 方法的概念](#1.1 方法的概念)
[1.2 语法格式](#1.2 语法格式)
[* 注意事项【与C不同】](#* 注意事项【与C不同】)
[1.3 return ------ 返回值的严格检查【比C语言严格】](#1.3 return —— 返回值的严格检查【比C语言严格】)
[2. 形参与实参的关系](#2. 形参与实参的关系)
[3. 方法重载](#3. 方法重载)
[3.1 什么是方法重载?为什么要方法重载?](#3.1 什么是方法重载?为什么要方法重载?)
[3.2 方法重载的规则](#3.2 方法重载的规则)
[4. 方法签名](#4. 方法签名)
[5. 递归](#5. 递归)
1. 方法基础知识
1.1 方法的概念
方法就是一个代码片段.类似于 C 语言中的 "函数"。方法存在的意义(不要背, 重在体会):
- 是能够模块化的组织代码(当代码规模比较复杂的时候).
- 做到代码被重复使用, 一份代码可以在多个位置使用.
- 让代码更好理解更简单.
- 直接调用现有方法开发, 不必重复造轮子.
1.2 语法格式
方法的语法格式:
修饰符 返回值类型 方法名称 ( [参数类型 形参 ...] ){
方法体代码;
[return 返回值];
}
//修饰符要等我们学到类和对象才能讲解清楚,目前我们只需要写上"public static"
例如:实现一个两个整数相加的方法
cpp
public class Method{
// 加法方法的定义
public static int add(int x, int y) {
return x + y;
}
}
* 注意事项【与C不同】
- 修饰符:现阶段直接使用public static 固定搭配。【C语言没有修饰符】
2. 方法名字:采用小驼峰命名。【C语言没有这种默认习惯】
- 在java当中,方法必须写在类当中,即方法的定义必须在类的局部域上。 (比如上面的加法方法,该方法就写在了Method类里)
【C语言中没有类的概念,函数定义要写在所有函数的外面,即在全局域上】
4. 方法不能嵌套定义。++【C语言也不允许函数嵌套定义】++
- java当中,没有方法的前置声明 ;不过方法定义写在main方法后面也能使用(这也是类的优势)。
【C语言中,如果前面没写函数的定义,就需要在前面写上前置声明,否则就无法使用该函数】
[]不能前置声明:
[]方法定义写在main后:
1.3 return ------ 返回值的严格检查【比C语言严格】
先说结论:(针对基础数据类型)
- 方法的返回值可以没有,没有时返回值类型必须写成void。否则系统会检查你是否有返回值,如果没有就会要求你完成返回语句return。 【java方法定义中返回类型是必不可少的 ,没有返回类型一定会报错;不像C语言,没有返回类型默认是返回int型】
- Java是一种强类型语言 ,因此有返回值时,返回值必须与声明的返回类型相同。eg:int型对应int型,long对应long,double对应double......
- 除非 返回值类型 < 返回类型,即它们可以发生隐式类型转换。eg:float(值)与double(返),short(值)与int(返)......
错误例子1:返回值类型是int > 返回类型是byte
错误例子2:返回值类型是double 与 返回类型是boolean 不相干
对于类类型和接口类型,还会涉及向上转型和向下转型。(这些知识会在 类与对象 以及 java数据 结构 中讲解,目前只是++简单了解++)
自动装箱和拆箱 :Java支持自动装箱和拆箱,这允许基本数据类型 与其对应的包装类之间进行转换。例如:
cpp
public Integer getNumber() {
return 42; // 自动装箱,将int类型的42转换为Integer对象
}
泛型方法:在泛型方法中,返回值的类型检查也遵循相同的规则。例如:
cpp
public <T> T getValue(T value) {
return value; // 返回值类型与方法签名中的泛型类型一致
}
2. 形参与实参的关系
Java中方法的形参就相当于sum函数中的自变量n,用来接收sum函数在调用时传递的值的。形参的名字可以随意 取,对方法都没有任何影响,形参只是方法在定义时需要借助的一个变量,用来保存方法在调用时传递过来的值。
cpp
public static int add(int a, int b){
return a + b;
}
add(2, 3); // 2和3是实参,在调用时传给形参a和b
注意:实参的值永远都是拷贝到形参中,形参和实参本质是两个实体。
代码示例: 交换两个整型变量
cpp
public class TestMethod {
public static void main(String[] args) {
int a = 10;
int b = 20;
swap(a, b);
System.out.println("main: a = " + a + " b = " + b);
}
public static void swap(int x, int y) {
int tmp = x;
x = y;
y = tmp;
System.out.println("swap: x = " + x + " y = " + y);
}
}
// 运行结果
swap中: x = 20 y = 10
main中: a = 10 b = 20
在swap函数交换之后,形参x和y的值发生了改变,但是main方法中a和b还是交换之前的值,即没有交换成功。
【原因分析】
实参a和b是main方法中的两个变量,其空间在main方法的栈(一块特殊的内存空间)中,而形参x和y是swap方法中 的两个变量,x和y的空间在swap方法运行时的栈中,因此:实参a和b 与 形参x和y是两个没有任何关联性的变量, 在swap方法调用时,只是将实参a和b中的值拷贝了一份传递给了形参x和y,因此对形参x和y操作不会对实参a和b 产生任何影响。
总结:对于基础数据类型来说, 形参相当于实参的拷贝 . 即传值调用。
【java中没有指针,要做到传址调用就需要学习类和对象】
3. 方法重载
3.1 什么是方法重载?为什么要方法重载?
方法重载(Method Overloading)是Java中的一种重要特性,它允许在同一个类中定义多个同名的方法,但这些方法必须具有不同的参数列表。
至于"为什么要方法重载",我们以加法器为例:
Java对于类型的检查比较严格,如果要写出加法的方法,一般来说我们要为int型数据设置一个方法addInt,为float型的数据设置方法addFloat,为long型的数据设置方法addLong......
这样做就很麻烦,于是Java中引入了方法重载的概念,于是不同数据类型的加法方法都可以用add来命名了。(虽然是共用一个名字,但是方法的详细定义是不同的)
3.2 方法重载的规则
如何构成重载:
- 方法名必须相同。
- 参数列表必须不同(参数的个数、参数的类型、类型的次序,其中一个不同都算不同 ) 。【注意:参数名称不同 不算作 参数表不同,并不构成重载】
- 与返回类型是否相同无关。
- 与方法体是否相同无关。
- 决定性因素:参数表不同。
编译器在编译代码时,会对实参类型进行推演,根据推演的结果来确定调用哪个方法
错误例子1:参数名称不同
错误例子2:返回类型不同
错误例子3:方法体不同
正确示范:
4. 方法签名
在同一个作用域中不能定义两个相同名称的标识符。比如:方法中不能定义两个名字一样的变量。那为什么类中就可以定义方法名相同的方法呢?
这是因为有方法签名。
方法签名即:经过编译器编译修改过之后方法最终的名字,它用于唯一标识一个方法。
具体方式:方法全路径名 + 参数列表 + 返回值类型,构成方法完整的名字。
(虽然返回类型不参与Java中方法的重载机制,但它是方法签名的一部分)
注意事项
- 访问修饰符(如
public
、private
等)和异常声明(如throws Exception
)不属于方法签名的一部分。- 方法体也不属于方法签名的一部分,方法体是方法的具体实现。
以下是一些Java中的方法签名示例:
cpp
// 方法签名1: 无参数,无返回值
public void doSomething() {
}
// 方法签名2: 一个int参数,无返回值
public void doSomething(int a) {
}
// 方法签名3: 两个int参数,无返回值
public void doSomething(int a, int b) {
}
// 方法签名4: 一个String参数,返回int
public int doSomething(String s) {
return 0;
}
// 方法签名5: 一个int参数,返回String
public String doSomething(int a) {
return "";
}
在上面的例子中,每个方法都有不同的参数列表,因此它们具有不同的方法签名。即使方法名相同,只要参数列表不同,它们就是不同的方法。
方法签名与方法重载的关系:
- 方法重载依赖于方法签名的不同:由于方法重载要求同名方法的参数列表必须不同,因此编译器可以通过比较方法签名来区分不同的重载方法。如果两个方法的方法名相同但参数列表不同,那么它们就具有不同的方法签名,从而可以构成重载关系。
总的来说,①方法签名 是用于唯一标识一个方法的关键要素,②而方法重载 则是通过改变方法签名中的参数列表来实现的。
5. 递归
一个方法在执行过程中调用自身, 就称为 "递归". 递归相当于数学上的 "数学归纳法", 有一个起始条件, 然后有一个递推公式.
例如:我们求 N! 起始条件: N = 1 的时候, N! 为 1. 这个起始条件相当于递归的结束条件. 递归公式: 求 N! , 直接不好求, 可以把问题转换成 N! => N * (N-1)!
递归的必要条件:
- 将原问题划分成其子问题,注意:子问题必须要与原问题的解法相同
- 递归出口
代码示例: 递归求 N 的阶乘
cpp
//main方法
public static void main(String[] args) {
int n = 5;
int ret = factor(n);
System.out.println("ret = " + ret);
}
//递归的阶乘方法
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;
}
// 执行结果
函数开始, 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
注意事项
- 一定要保证函数在各种情况下都有方法出口,否则会报错并要求你写上其他出口。
【C语言中不强制要求每种情况下都有出口】
例如:
本期分享完毕,感谢大家的支持Thanks♪(・ω・)ノ