Java学习之路——方法
1.方法的基本定义
方法就是一个代码片段,是进行代码可重复利用的一种技术手段,通过方法结构保存需要重复使用的代码片段,实现可重复的调用,方法的基本语法如下:
public static 方法返回值 方法名称 ([参数列表]){
方法体代码;//需要重复执行的操作
}
代码示例
public class Text6 {
public static void main(String[] args) {
int a = 10;
int b = 7;
int ret = sum(a,b); //方法的调用,将a,b的值传入sum()方法,使用ret接收返回值
System.out.println(ret);
}
public static int sum(int x,int y){ //一个求传入两数字和的方法
return x+y; //return代表方法的结束,return后跟的是方法最终返回的值。
}
}
注意
1.public和static两个关键字在此处具有特殊含义,暂时先不深究,此后会学习。
2.方法定义时,可以没有参数,有参数的话要制定类型。
3.方法定义时,可以没有返回值,将返回值类型写为void即可。
4.方法定义时的参数称为“形参”,方法调用时的参数称为“实参”。
5.方法必须定义在类之中,代码在调用位置的上方或下方都可。
6.Java中没有“函数声明”的概念。
形参和实参的关系
观察交换两个整型变量的代码
public class Text6 {
public static void main(String[] args) {
int a = 10;
int b = 7;
System.out.println("交换前a="+ a + " " + "b="+ b);
exc(a,b);
System.out.println("交换前a="+ a + " " + "b="+ b);
}
public static void exc(int x,int y){
System.out.println("交换前x="+ x + " " + "y="+ y);
x = x^y; //通过异或交换x和y的值
y = x^y;
x = x^y;
System.out.println("交换后x="+ x + " " + "y="+ y);
}
}
结果如下
通过上面的代码,我们发现在exc方法执行时交换了x,y的值,但是a和b的值在方法执行后并未交换,上述代码中的a和b为实参,x和y则是形参。所以对于基础数据类型,形参相当于实参的拷贝,传值调用,改变形参的值不会改变实参的值。
2.方法的重载
方法重载的定义
方法重载是方法名称进行重用的一神技木形式,其最主要的特点为"方法名称相同。参数的类型或个数不同".在调用吋会根据传递的参数类型和个数不同执行不同的方法体。
如果说现在有一个方法名称有可能要执行数据的加法操作.例如. 一个sum()方法.它可能执行2个整数的相加。也可能执行3个整数的相加或者可能执行2个小数的相加。很明显.在这祥的情况下一个方法体肯定无法满足要求,需要为sum()方法定义多个不同的方法体, 所以此时就需要方法重载概念的支持。
重载的规律
1.方法名相同
2.方法参数不同(参数个数或参数类型)
3.方法返回值类型不影响重载
参考代码
public class Text6 {public static void main(String[] args) {
int num_1 = sum(3,5);
double num_2 = sum(1.1,2.5,3.2);
System.out.println("两个整数和为:"+ num_1 +"\n三个个小数和为:"+num_2);
}
public static int sum(int a,int b){
return a+b;
}
public static double sum(double a,double b,double c){
return a+b+c;
}
}
结果如下
3.方法递归调用
方法递归的定义
递归调用是一种特殊的方法嵌套调用形式,指的是方法自己调用自己的形式,但是在进行递归调用时必须要满足以下的条件,一旦处理不当就会导致内存栈溢出。
递归调用必须要有结束的条件
每次调用的时候都需要根据需求改变传递的参数的内容
递归相当于数学中的“数学归纳法”,有一个起始条件(即递归调用的结束条件)和一个递推公式(即每次改变参数的内容)
例如求N!
起始条件:N=1的时候N!为1,相当于递归中的结束条件。
递归公式:N!= N*(N-1)!
所以我们可以使用递归来求N的阶乘
递归求N的阶乘
import java.util.Scanner;
public class Text4 {public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要求阶乘的数字:");
int a = sc.nextInt();
int fa_1 = fac(a);
System.out.println(a + "的阶乘为:"+fa_1);
}
public static int fac(int n){
if( n == 1 ) {
return 1;
}else{
return n * fac( n-1);
}
}
}
结果如下
递归执行过程分析
递归的过程不太容易理解,要理解并掌握递归需要大量的代码积累,要理解递归必须知道递归是在方法执行的过程中先进行“递”,然后“递”到最后一个时,有一个返回值“归”,接着再一个个“归”。我们可以给上面求阶乘的代码中加上日志,然后观察递归执行的过程。
递归求N的阶乘,加日志版
import java.util.Scanner;
public class Text6 {public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要求阶乘的数字:");
int a = sc.nextInt();
int fa_1 = fac(a);
System.out.println(a + "的阶乘为:"+fa_1);
}
public static int fac(int n){
System.out.println("函数开始,n=" + n);
if( n == 1 ) {
System.out.println("函数结束,n=" + n);
return 1;
}else{
int ret= n * fac( n-1);
System.out.println("函数结束,n=" + n + " ret=" + ret);
return ret;
}
}
}
结果如下
通过上述的代码中的日志,我们可以清楚地看到,递归调用先进行“递”的过程,最后在进行“归”的过程。
递归调用的一些应用
递归求斐波那契数列的第 N 项
import java.util.Scanner;
public class Text1 {public static void main(String[] args) {
System.out.println("请输入你要斐波那契数组的第几项:");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println("斐波那契数列的第" + n +"项为:"+ fib(n));
}
public static int fib(int n){
if( n == 1 ||n == 2){
return 1;
}
return n+fib(n-1);
}
}
结果如下
按顺序打印一个数字的每一位
public class Text3 {public static void main(String[] args) {
pri(1357);
}
public static void pri(int n){
if(n > 9){
pri(n/10);
System.out.print(n%10 + " ");
}else {
System.out.print(n + " ");
}
}
}
结果如下
递归何时使用?
有些问题天然就是使用递归方法定义的(例如斐波那契数列,二叉树等),此时使用递归来解就很容易
有些问题使用递归和使用非递归(循环)都可以解决,那么此时更推荐使用循环,因为非递归程序比递归程序更加高效。