方法概述、重载、递归
一、概述
① 定义
Java方法是语句的集合,它们在一起执行一个功能。
- 解决一类问题的步骤的有序组合
- 包含于类或对象中
- 可在其他地方被引用
② 命名规则
- 1.方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写,不使用连接符。(例如:addPerson)
- 2.下划线可能出现在 JUnit 测试方法名称中用以分隔名称的逻辑组件。一个典型的模式是:test_。(例如 testPop_emptyStack)
③ 组成部分
方法的组成部分如上图所示,其中修饰符表示方法访问权限、是否静态等等,表示方法方法访问权限的修饰符,具体如下所示:
权限修饰符 | 本类 | 本包 | 子类 | 外部包 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
default | √ | √ | × | × |
private | √ | × | × | × |
注意:
java的访问控制是停留在编译层的,也就是它不会在.class文件中留下任何的痕迹,只在编译的时候进行访问控制的检查。其实,通过反射的手段,是可以访问任何包下任何类中的成员,例如,访问类的私有成员也是可能的。
④ 不定参数
当我们不能确定输入参数的个数时,就需要用到不定参数。
其一般形式如下(这里以int为例):
public static void voidName(int... a){ //不定参数本质为数组
//执行代码块(方法体)
}
不定参数的本质是数组,下面我们将举例验证:
① 直接使用数组:
public static int sum(int[] a){
int result = 0;
for(int i = 0; i < a.length; i++){
result += a[i];
}
return result;
}
② 使用不定参数形式,间接使用数组:
public static int sum(int... a){
int result = 0;
for(int i = 0; i < a.length; i++){
result += a[i];
}
return result;
}
在调用时,会感受到明显的差异:
① 直接使用数组:
int[] arr = { 1, 2, 3, 6, 5, 4, 5, 6, 7 };
System.out.println(sum(arr));
② 使用不定参数形式,直接 / 间接使用数组:
int[] arr = { 1, 2, 3, 6, 5, 4, 5, 6, 7 };
System.out.println("不定参数,直接使用数组:" + sum(arr));
System.out.println("不定参数,间接使用数组:" + sum(1, 2, 3, 6, 5, 4, 5, 6, 7));
- 可以看到,直接使用数组时,用户需提前定义好存储参数的数组;而使用不定参数形式,可省略此步骤,十分便捷。
优点:更方便有效地复用本段代码,增强代码的可复用性。
二、重载
① 定义
定义一些名称相同的方法,通过定义不同的输入参数来区分这些方法,然后再调用时,VM就会根据不同的参数样式,来选择合适的方法执行。
② 举例
//add方法构成重载
public static int add(int a , int b) {
return a + b;
}
public static int add(int a , int b , int c) {
return a + b + c;
}
public static double add(double a , double b , double c) {
return a + b + c;
}
注意:
- 方法重载与方法的访问修饰符、返回值类型无关
上图为在编译环境中提示出现语法错误(存在相同名称的方法),即使在main方法中正确调用,程序也不会执行。
三、递归
① 定义
程序调用自身的编程技巧称为递归( recursion)。
思想:一个函数在其定义或说明中直接或间接调用自身的一种方法。
要素:需要边界条件和算法。
② 练习
Ⅰ. 斐波那契数列
循环:
public int fibonacci(int n) {
int a = 1;
int b = 1;
int c = 0;
for (int i = 3; i <= n; i++) {
c = a + b;
a = b;
b = c;
}
return c;
}
递归:
public int fibonacci(int n) {
//递归出口
if (n == 1 || n == 2) {
return 1;
}
return test(n - 1) + test(n - 2);
}
Ⅱ. 计算阶乘
循环:
public int factorial(int n) {
int count = 1;
for (int i = 2; i <= n; i++) {
count *= i;
}
return count;
}
递归:
public int factorial(int n) {
// 递归出口
if (n == 1) {
return 1;
} else {
return n * test(n - 1);
}
}
Ⅲ. 辗转相除 求最大公因数
循环:
public int greatestCommonDivisor(int m, int n) {
while (true) {
if (m % n == 0) {
return n;
}
int temp = m;
m = n;
n = temp % n;
}
}
递归:
public int greatestCommonDivisor(int m, int n) {
//递归出口
if (m % n == 0) {
return n;
}
return test(n, m % n);
}
Ⅳ. 判断一个数组是否有序
循环:
public boolean isOrder(int[] a) {
boolean b = true;
for (int i = 0; i < a.length - 1; i++) {
if (a[i] > a[i + 1]) {
b = false;
break;
}
}
return b;
}
递归:
public boolean isOrder(int[] a, int length) {
if (length == 1) {
//递归出口
return true;
}
if (a[length - 1] < a[length - 2]) {
//递归出口
return false;
}
return test(a, length - 1);
}