一、函数的概述

1、什么是函数?

(1)为了解决某一特定问题,具有名称的的代码集合。函数也就是现实中的一种行为动作!!!。
(2)函数就是定义在类中的具有特定功能的一段独立小程序。
特点:定义函数可以将功能代码进行封装便于对该功能进行复用,函数只有被调用才会被执行。

2.函数的定义

权限修饰符 函数类型修饰符 返回值类型/void 函数名([参数列表]){ 
      执行语句; 
      return 返回值; 
}

(1)java中函数是属于类的!!必须定义在类中!!!所以说函数是类成员
(2)java中:静态方法(static)没有办法直接调用非静态方法!!!只能调用静态方法
(3)参数列表:参数列表有若干个 参数类型,参数名… 组成 主要用于接收外界传递给函数的一些数据
(4)return:仅仅表示结束当前函数,如果有返回值,则函数结束前将返回值返回给调用者
(5)返回值:指的就是这一具有独立功能的代码块的计算结果,需要传递给外界 配合return
(6)返回值类型:就是返回值的数据类型(可兼容)
(7)return与void不能并存,有void就不能出现return 返回值;,有return 返回值,定义函数时不可出现void。

定义函数时,时刻把握如下两点,基本就可以完成函数的定义:
 1:这个功能的结果是什么?其实就是明确返回值类型。
 2:这个功能需要未知内容是什么?其实就是明确参数列表

示例学习:打印分数等级

public class TestVoidMethod { 
   public static void main(String[] args) { 
      System.out.print("The grade is "); printGrade(78.5);                   
      System.out.print("The grade is ");
      printGrade(59.5); 
   }
   public static void printGrade(double score) {
      if (score >= 90.0) { 
         System.out.println('A'); 
      } else if (score >= 80.0) { 
         System.out.println('B'); 
      } else if (score >= 70.0) { 
         System.out.println('C'); 
      } else if (score >= 60.0) {
         System.out.println('D'); 
      } else { 
         System.out.println('F');
      } 
  } 
}

3.函数的调用

函数是无法自己执行的!!!必须通过调用才可以执行!!!
如果定义的是static的方法,调用函数用如下方法:

函数名称([参数列表]);

如果定义的函数不是static的方法,调用函数用如下方法:

必须使用构建对象的方式
类名 对象名=new 类名();
对象名.函数名称([参数列表]);

class TestFun01 {
	public static void main(String[] args) {
	    // 注意,在main函数中,如果要调用非静态方法,
		// 必须使用构建对象的方式
		TestFun01 tf = new TestFun01();
		tf.sayHello();
	}

	public  void sayHello() {
		System.out.println("hello, I am function……");
	}
}

4.局部变量

局部变量(本地变量):定义在函数中的变量叫做局部变量
局部变量,存在于定义其的作用域内,如此例,则它的存活区域就是main函数内部,函数跳出后它就被销毁

成员变量,存在于定义其的对象存活区域内,如此例,则它的存活期由一个类a的对象实例化开始到销毁这个对象结束

5.函数的运行原理

每当调用一个方法时,系统会创建一个活动记录(也称为活动框架),用于保存方法中的参数和变量。活动记录置于一个内存去榆中,称为调用堆栈(call stack)。调用堆栈也称为执行堆栈、运行时堆栈,或者一个机器堆栈,常简称为“堆栈”。当一个方法调用另一个方法时,调用者的活动记录保持不动,一个新的活动记录被创建用于被调用的新方法。一个方法结束返回到调用者时,其相应的活动记录也被释放。

二、重载

1、什么是重载?

函数名称相同,函数的参数的个数或者类型不同,调用的时候,自动匹配对应的函数

(1)与权限没关系,与返回值类型没关系,与参数名没关系,只有和参数类型的排列组合有关系(注意一下参数类型的向下兼容问题)
(2)重载的好处就在于我们可以扩展函数的功能(函数重名,但是参数类型不一样,执行内容也可以不一样)

函数重载所有编程语言都有的吗?
    函数重载现象是强数据类型语言(java、C、C++、C#)所特有的现象
	弱数据类型语言(javascript、python、ruby)是不具备函数重载

示例学习:多个值的max()函数

public class TestMethodOverloading { 
   public static void main(String[] args) { 
		     System.out.println("The maximum between 3 and 4 is " 
		                                        +max(3, 4)); 
		     System.out.println("The maximum between 3.0 and 5.4 is " 
		                                    + max(3.0, 5.4));
		     System.out.println("The maximum between 3.0, 5.4, and "
		     		+ "10.14 is "+ max(3.0, 5.4)); 
		   }
		   public static int max(int num1, int num2) { 
		      if (num1 > num2) {
		            return num1;
		      }else{
		            return num2; 
		      }
		   }
		   public static double max(double num1, double num2) { 
		      if (num1 > num2) {
		    	  return num1;
		      } else {
		    	  return num2; 
		      }   
		   }
 }

三、函数的递归

1、什么是递归?

函数自身调用自身

1.递归其实是分治法的一种实现方式(一种实现思路)。
2.递归就是函数在进栈,进栈的次数多了,势必会占内存,无法避免的
3.在某些问题上,递归所写的代码要比迭代写的代码少
4.在某些问题上,迭代是写不出来的,所以只能用递归

示例学习:递归实现斐波那契数列

import java.util.Scanner;
public class Test{
	public static int a(int q){
		if(q==1 || q==2){
		   return 1;
		}
		return a(q-1)+a(q-2);
	}
	public static void main(String[] args){
		Scanner sc=new Scanner(System.in);
		System.out.print("请输入一个数字:");
		int q=sc.nextInt();
	    int w=a(q);
		System.out.println(w);
	
	}

示例学习:汉诺塔问题

public class Hanoi { 
   public static void main(String[] args) { 
       hanoi(10, "X", "Y", "Z"); 
   }
   public static void hanoi(int n, String begin, 
       String mid, String end){ 
       if (n == 1) {
            System.out.println(begin + " -> " + end); 
        } else { 
              hanoi(n - 1, begin, end, mid); 
              System.out.println(begin + " -> " + end); 
              hanoi(n - 1, mid, begin, end);
         }
     }
 }