04.方法的使用
方法其实就是一个代码片段,类似于我们C语言中的“函数”。// 方法定义修饰符 返回值类型 方法名称([参数类型 形参 ...]){方法体代码;[return 返回值];PS:现阶段直接使用public static 固定搭配如果方法有返回值,返回值类型必须要与返回的实体类型一致,如果没有返回值,必须写成void采用小驼峰命名如果方法没有参数,()中什么都不写,如果有参数,需指定参数类型,多个参数之
目录
方法的概念及使用
什么是方法
方法其实就是一个代码片段,类似于我们C语言中的“函数”。
方法的的定义
// 方法定义
修饰符 返回值类型 方法名称([参数类型 形参 ...]){
方法体代码;
[return 返回值];
}
PS:
- 修饰符:现阶段直接使用public static 固定搭配
- 返回值类型:如果方法有返回值,返回值类型必须要与返回的实体类型一致,如果没有返回值,必须写成
void- 方法名字:采用小驼峰命名
- 参数列表:如果方法没有参数,()中什么都不写,如果有参数,需指定参数类型,多个参数之间使用逗号隔开
- 方法体:方法内部要执行的语句
- 在java当中,方法必须写在类当中
- 在java当中,方法不能嵌套定义
- 在java当中,没有方法声明一说
方法调用的执行过程

PS:
- 定义方法的时候, 不会执行方法的代码. 只有调用的时候才会执行.
- 一个方法可以被多次调用.
实参和形参的关系
在数学中,我们学过自变量与因变量。
那么,在Java方法中,其实形参就相当于数学中的自变量。
形参的名字可以随意取,对方法是没有影响的。因为它只是方法在定义时需要借助的一个变量,用来保存方法在调用时传递过来的值。
public static int getSum(int N){ // N是形参
return (1+N)*N / 2;
}
getSum(10); // 10是实参,在方法调用时,形参N用来保存10
getSum(100); // 100是实参,在方法调用时,形参N用来保存100
ps:
在Java中,实参的值永远都是拷贝到形参中的,形参和实参本质上是两个实体。
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的值发生改变了,但a和b的值还是交换之前的值。
也就是说,形参并不影响实参的值。
注意:对于基础类型来说, 形参相当于实参的拷贝. 即 传值调用
没有返回值的方法
在Java中方法的返回值是可以选择的,有的时候可以没有返回值,但在没有返回值时,方法的返回值类型必须写成void。
class Test {
public static void main(String[] args) {
int a = 10;
int b = 20;
print(a, b);
}
public static void print(int x, int y) {
System.out.println("x = " + x + " y = " + y);
}
}
方法重载
为什么需要方法重载
当我们定义一个add方法,并设定它的参数为int类型,在我们调用add方法,并给它传double类型的参数时,就会报错。
public class TestMethod {
public static void main(String[] args) {
int a = 10;
int b = 20;
int ret = add(a, b);
System.out.println("ret = " + ret);
double a2 = 10.5;
double b2 = 20.5;
double ret2 = add(a2, b2);
System.out.println("ret2 = " + ret2);
}
public static int add(int x, int y) {
return x + y;
}
}
// 编译出错
Test.java:13: 错误: 不兼容的类型: 从double转换到int可能会有损失
double ret2 = add(a2, b2);
^
这个原因是因为,参数类型不匹配,所以不能使用我们目前已经定义好的add方法。
此时有几种解决方法。
其中一种简单粗暴的解决方法,就是再定义一个add方法,不过这里要区分开来。
public class TestMethod {
public static void main(String[] args) {
int a = 10;
int b = 20;
int ret = addInt(a, b)
System.out.println("ret = " + ret);
double a2 = 10.5;
double b2 = 20.5;
double ret2 = addDouble(a2, b2);
System.out.println("ret2 = " + ret2);
}
public static int addInt(int x, int y) {
return x + y;
}
public static double addDouble(double x, double y) {
return x + y;
}
}
这样确实能解决问题,但这样的话,我们就需要定义许多方法名,然而,这么多方法名,谁能记得住呢?我们能不能将所有的add方法都命名为add呢?
答案是可以的。
方法重载的概念
这里就是方法重载的概念了,那么什么是方法重载呢?
在我们日常生活中,经常会出现一词多用的情况,例如河南人的“中”,在不同的场景,会表示不同的含义。
那么,在Java中,方法可不可以“一方法多用”呢?当然可以!
在Java中,如果多个方法的名字相同,但参数列表不同,我们就说这几种方法被重载了。
public class TestMethod {
public static void main(String[] args) {
add(1, 2); // 调用add(int, int)
add(1.5, 2.5); // 调用add(double, double)
add(1.5, 2.5, 3.5); // 调用add(double, double, double)
}
public static int add(int x, int y) {
return x + y
}
public static double add(double x, double y) {
return x + y;
}
public static double add(double x, double y, double z) {
return x + y + z;
}
}
方法重载好用是好用,但是我们要注意几点。
1.方法名必须相同
2.参数列表必须不同(参数的个数不同、参数的类型不同、类型的次序必须不同)
3.与返回值类型是否相同无关
4.编译器在编译代码时,会对实参类型进行推演,根据推演的结果来确定调用哪个方法
// 注意:两个方法如果仅仅只是因为返回值类型不同,是不能构成重载的
public class TestMethod {
public static void main(String[] args) {
int a = 10;
int b = 20;
int ret = add(a, b);
System.out.println("ret = " + ret);
}
public static int add(int x, int y) {
return x + y;
}
public static double add(int x, int y) {
return x + y;
}
}
// 编译出错
Test.java:13: 错误: 已在类 Test中定义了方法 add(int,int)
public static double add(int x, int y) {
^
1 个错误
方法签名
我们之前了解到,在同一个作用域中不能定义两个相同名称的标识符。比如:方法中不能定义两个名字一样的变量。
那为什么类中就可以定义方法名相同的方法呢?
这是因为虽然方法名是一样的,但在Java底层逻辑中,相同方法名的方法签名是不一样的。
这里就涉及到一个新概念,也就是方法签名。
方法签名:经过编译器编译修改过之后方法最终的名字。
具体方式:方法全路径名+参数列表+返回值类型,构成方法完整的名字。
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);
}
}
上述代码经过编译之后,然后使用JDK自带的javap反汇编工具查看,具体操作:
1.先对工程进行编译生成.class字节码文件
2.在控制台中进入到要査看的.class所在的目录
3.输入:javap -v 字节码文件名字即可

这里的方法签名中存在一些特殊符号,这些特殊符号的含义如下:
|
特殊字符 |
数据类型 |
|
V |
void |
|
Z |
boolean |
|
B |
byte |
|
C |
char |
|
S |
short |
|
I |
int |
|
J |
long |
|
F |
float |
|
D |
double |
|
[ |
数组(几个[表示几维数组) |
|
L |
引用类型,以L开头,;结尾,中间是引用类型的全类名 |
递归
递归的概念
在小时候,我们就听过一个故事。
从前有坐山,山上有座庙,庙里有个老和尚给小和尚将故事,讲的就是:
"从前有座山,山上有座庙,庙里有个老和尚给小和尚讲故事,讲的就是:
"从前有座山,山上有座庙..."
"从前有座山……"
如果老和尚一直不睡去,那么这个故事是不是一直会继续。
这便是递归的具象化。
那么,递归的具体概念是怎样呢?
一个方法在执行过程中调用自身,就称为“递归”。
递归就相当于数学中的“数学归纳法”,它有一个起始条件,也有一个递推公式。
ps:
1. 将原问题划分成其子问题,注意:子问题必须要与原问题的解法相同
2. 递归出口
publicstaticvoidmain(String[]args){
intn=5;
intret=factor(n);
System.out.println("ret="+ret);
}
publicstaticintfactor(intn){
if(n==1){
return1;
}
returnn*factor(n-1); //factor调用函数自身
}
//执行结果ret=120
递归执行过程分析
递归的程序的执行过程不太容易理解, 要想理解清楚递归, 必须先理解清楚 "方法的执行过程", 尤其是 "方法执行结束之后, 回到调用位置继续往下执行"。
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

上述程序按照序号中标识的(1)到(8)这样的顺序去执行。
更多推荐
所有评论(0)