方法就是C语言中常说的函数,这里换了个说法而已;包类似于C语言中的头文件,但有区别。
方法
这里,我们来个例子来体会一个方法的用处:
求1! + 2! + 3! + 4! + 5!
public class Test {
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i <= 5; ++i) {
int temp = 1;
for (int j = 1; j <= i; ++j) {
temp *= j;
}
sum += temp;
}
System.out.println("1! + 2! + 3! + 4! + 5! = " + sum);
}
}
可以看到,上述两个for循环也可以求出结果,但是可读性不太好,我们使用方法来解决一下这个问题。
public class Test {
public static void main(String[] args) {
int sum = 0;
for (int num = 1; num <= 5; ++num) {
sum += factor(num);
}
System.out.println("1! + 2! + 3! + 4! + 5! = " + sum);
}
// 计算num的阶乘
private static int factor(int num) {
int ret = 1;
for (int i = 1; i <= num; ++i) {
ret *= i;
}
return ret;
}
}
这里,我们将求阶乘封装成一个方法,代码逻辑看起来就清晰了很多,而且这个求阶乘的代码还可以被复用。
再来一个例子,实现两个整数相加:
public class Test {
public static void main(String[] args) {
int numA = 10;
int numB = 20;
int sum = add(numA, numB);
System.out.println(numA + " + " + numB + " = " + sum);
}
private static int add(int numA, int numB) {
return numA + numB;
}
}
实参和形参的关系
我们来看一个代码:
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("before swap: a = " + a + " b = " + b);
swap(a, b);
System.out.println("after swap: a = " + a + " b = " + b);
}
private static void swap(int numA, int numB) {
int temp = numA;
numA = numB;
numB = temp;
}
}
从结果可以看出,swap并没有完成a和b的交换。从这里可以看出,Java和C语言一样,实参是形参的一份拷贝,修改形参的值,不会影响到实参。
如果要做到修改形参可以改变形参,可以传引用类型(例如:数组),下面看一个例子:
public class Test {
public static void main(String[] args) {
int[] arr = new int[]{10, 20};
System.out.println("arr[0] = " + arr[0] + " arr[1] = " + arr[1]);
swap(arr);
System.out.println("arr[0] = " + arr[0] + " arr[1] = " + arr[1]);
}
private static void swap(int[] arr) {
int temp = arr[0];
arr[0] = arr[1];
arr[1] = temp;
}
}
注意:Java中的方法都是和类关联在一起的;Java的方法必须写到类内。Java中的方法的定义位置,可以放在调用代码的上面,也可以放下面。Java中没有函数声明这个东西。
方法的重载
我们来看一个场景:
public class Test {
public static void main(String[] args) {
System.out.println(10 + " + " + 20 + " = " + add(10, 20));
System.out.println(10.10 + " + " + 20.20 + " = " + add(10.10, 20.20));
}
private static int add(int numA, int numB) {
return numA + numB;
}
}
针对上述类型不匹配的问题,我们需要再写一个方法来解决这个问题。
public class Test {
public static void main(String[] args) {
System.out.println(10 + " + " + 20 + " = " + addInt(10, 20));
System.out.println(10.10 + " + " + 20.20 + " = " + addDouble(10.10, 20.20));
}
private static int addInt(int numA, int numB) {
return numA + numB;
}
private static double addDouble(double numA, double numB) {
return numA + numB;
}
}
上述的写法是对的,但是Java认为这样的写法太丑了,于是提供了函数重载,我们直接来看一下函数重载的效果。
public class Test {
public static void main(String[] args) {
System.out.println(10 + " + " + 20 + " = " + add(10, 20));
System.out.println(10.10 + " + " + 20.20 + " = " + add(10.10, 20.20));
}
private static int add(int numA, int numB) {
return numA + numB;
}
private static double add(double numA, double numB) {
return numA + numB;
}
}
从上述可以看出,同一个方法名,提供不同版本的实现,称为方法重载。
重载的规则:
- 在同一个类中;
- 方法名相同;
- 方法的参数不同(参数个数或者参数类型);
方法的返回值类型不影响重载:
我们来看一个例子理解一下:
public class Test {
public static void main(String[] args) {
System.out.println(10 + " + " + 20 + " = " + add(10, 20));
}
private static int add(int numA, int numB) {
return numA + numB;
}
private static double add(int numA, int numB) {
return numA + numB;
}
}
方法递归
一个方法在执行过程中调用自身,就称为“递归”。
我们来看一个例子:递归求5的阶乘。
public class Test {
public static void main(String[] args) {
System.out.println("5! = " + factor(5));
}
private static int factor(int num) {
if (num == 1) {
return 1;
}
return num * factor(num - 1);
}
}
我们给程序加一些日志,再来看一下:
public class Test {
public static void main(String[] args) {
System.out.println("5! = " + factor(5));
}
private static int factor(int num) {
System.out.println("进入方法,num = " + num);
if (num == 1) {
System.out.println("方法调用结束,num = " + num + ", ret = " + 1);
return 1;
}
int ret = num * factor(num - 1);
System.out.println("方法调用结束,num = " + num + ", ret = " + ret);
return ret;
}
}
我们再来函数调用图来理解一下。