第五章 函数

第五章 函数



5.1函数的概念

(函数不能单独成为一个类,不能在函数中再成立一个函数,只能在其他函数之外,当前类之中)

什么是函数?

函数的定义就是指一段具有独立功能的代码,可以减少代码冗余,提高程序的利用率和效率。

我们应该如何定义函数?
  • 需要一个封闭的空间,将这段独立性的代码进行封装,用{ }
  • 需要对每一个封闭的空间进行命名,函数名
  • 函数所需要的一些原始数据
  • 函数所产生的一些结果数据

函数的语法格式

	修饰符 函数类型  返回值类型  函数名(数据类型 数据1,数据类型 数据2,......){
			独立功能的代码片段;
			return 函数的计算结果;
	}
  • 修饰符: 指的是函数的访问权限,public private (默认 protected)
  • 函数的类型:函数的分类,本地函数native,静态函数static,同步函数synchronized
  • 返回值类型:指的就是函数计算结果的数据类型 如果函数没有返回值 则为void
  • 函数名:就是函数的名称
  • 参数列表:指的是外界 向函数传入的数据(实际参数),由这些参数变量进行接收(形式参数)
  • 函数体:具有独立功能的代码片段
  • return:仅仅表示函数结束!如果函数有返回值,则return 后跟返回值;如果没有返回值,则return可以不写,但是是存在的(隐藏的)如果有返回值类型(除void)return后必须有值

根据形参和返回值来看,函数有如下几个分类

  • 有参数没返回值

将三个字符串的反转,并拼接打印

public class Sample06{
    public static void main(String[] args){
        print("123","456","789");
    }
    public static void print(String s1,String s2,String s3){
        System.out.println(reverses(s1) + reverses(s2) + reverses(s3));
    }
    public static String reverses(String s){
        String res = "";
        for (int i = s.length() - 1; i >= 0;i--){
            char ch = s.charAt(i);
            res = res + ch ;
        }
        return res;
    }
}
  • 有参数有返回值

求三个数字当中的最大值

public class Sample04{
    public static void main(String[] args){
        // Scanner input = new 
        int max = getMax(1,2,3);
        System.out.println(max);
    }
    public static int getMax(int a,int b,int c){
        /*
        if (a >= b && a >= c){
            return a;
        } else if (b >= a && b >= c){
            return b;
        } else {
            return c;
        }
        */
        if (a >= b && a >= c){
            return a;
        } 
        if (b >= a && b >= c){
            return b;
        } 
        if (c >= b && c >= a) {
            return c;
        }
        return -1
    }
}

计算一个数字a的b次幂

public class Sample05{
    public static void main(String[] args){
        double  i = getPow(2,2);
        System.out.println(i);
    }
    public static double getPow(int a,int b){
        double pow = 1.0;
        if ( a == 0) {
            return 0;
        }
        if (b == 0) {
            return 1;
        }
        for (int  i = 0;i < Math.abs(b);i++){
            pow *= a;
        }
        return b > 0 ? pow : 1 / pow;
        
            
    }
}
  • 没参数有返回值
  • 没参数没返回值

总结
当函数的返回值类型不为void的时,return后一定要加返回结果。
当函数返回值类型为void时或无返回值,在主函数中不需要定义一个变量来接收,直接调用即可,并且函数中需要加入System.out.println()来打印。
当函数没有参数时,参数的获取来自于其他地方而不是主函数,

定义函数时需要考虑的有哪些?

  • 函数的运行有哪些未知的参数?
  • 函数的运行结果有是什么?
  • 明确参数和结果
  • 明确内容和返回
  • 函数到底要干什么?
  • 尽量将独立功能且重复性较高的代码片段提取出来

5.2函数的运行原理

函数的运行是基于栈运行的
栈:是一种先进后出的容器,我们这里所说的栈是指JVM中的栈内存空间
每一个函数,叫做栈帧,栈帧中所包含的内容有函数的定义,参数列表,函数的执行内容代码
每一个函数要运行,就相当于这个栈帧进入到栈内存中–入栈
如果一个函数即将结束,将这个栈帧从栈移出–出栈
如果栈内存中有多个栈帧,运行的是最上面的栈帧,底下的栈帧暂停运行,直到该栈帧为栈顶元素
比如:主函数先进栈,开始逐行运行,如果执行到第n行,调用另外一个函数A,则主函数在第n行暂停运行,将另一个函数A的栈帧入栈,再继续逐行运行,直到函数A的内容执行完毕,函数A出栈,主函数接着从第n行继续向下执行。以此类推。

5.3函数的重载

同一个类可以出现多个同名函数,这个现象叫做函数的重载(overload)
如何来区分同名函数是否是重载关系?
前提是先必须是同名,并且和返回值类型无关(返回值类型只和函数的计算功能相关),和权限也无关,和形式参数的名称也无关!只和形式参数的数据类型有关(数量,排列组合)

public static void show(int a,float b,char c){}

下列哪些函数是该函数的重载:
- int show(int x,float y,char z):不算重载 数据类型都是int float char
- void show(float b,int a,char c):算重载,顺序不一样 float int char
- void show(int a ,int b,int c):算重载,顺序不一样
- double show():算重载,参数数量不一样
寻找重载函数的流程:

	 1. 看是否有确切的参数定义匹配,int int 找int int
	 2. 看是否有可兼容的参数定义匹配,int int 找double double 或 int double或double int
	 3. 如果可兼容的参数定义匹配较多,会报引用类型错误 引用不明确

总结

double可以向下兼容int
先找最近的,再找相近的,再找可以兼容的

5.4函数的递归

函数的递归就是指函数自身调用自身。

  • 但凡迭代能够解决的问题,递归都可以解决;递归可以解决的问题,迭代就不一定
  • 相对而言,从内存的角度而言,函数如果过多的自我调用,势必会对内存不友好,占用过多
  • 通常来讲,同样的问题用递归写要比用迭代写代码量较小
    写递归时,一定要先确定递归结束条件-递归边界

举例

用递归实现前100项求和

1+2 +3+4+…+100
f(1) = 1 //函数边界
f(2) = 2 +f(1)

f(99) = 99 + f(98)
f(n) = n + f(n - 1)
1 x=1
f(x)=
f(x-1) +x x>1

public class Sample{
	public static void main(String[] args){
		int sum = Sum(100);
		System.out.println(Sum(10000000));//StackOverflowError
		System.out.println(sum);
	}
	public static int Sum(int a){
		int sum = 0;
		if (a == 1){
			return 1;
		} else {
			sum = Sum(a - 1) + n;
			return sum;
		}
	}
}
递归实现斐波那契数列

1 1 2 3 5 8 13 21 …
1 x=1,2
f(x)
f(x-1) + f(x-2) x>2

public class Sample{
	public static void main(String[] args){
		//递归
		System.out.println(Sum(10));
		//迭代
		System.out.println(fibo_it(30));
	} 
	public static int fibo_it(int x){
		if (x == 1 || x == 2) {
			return 1;
		}
		int a = 1;
		int b = 1;
		int c = 0;
		for (int i = 3;i <= x;i++){
			c = a + b;
			a = b;
			b = c;
		}
		return c;
	}
	public static int Sum(int n){
		int sum = 0;
		if (n == 1 || n == 2){
			return 1;
		} else {
			sum = Sum(n - 1) + Sum(n - 2);
			return sum;
		}
	}
}
递归解决汉诺塔问题
/*
前4个  x->z
	前3个 x->y
		前2个 x->z
			前1个 x->y
			第2个 x->z
			前1个 y->z
		第3个 x->y
		前2个 z->y
			前1个 z->x
			第2个 z->y
			前1个 x->y
	第4个 x->z
	前3个 y->z
		前2个 y->x
			前1个 y->z
			第2个 y->x
			前1个 x->y
		第3个 y->z
		前2个 x->z
			前1个 x->y
			第2个 x->z
			前1个 y->z
*/
public class Sample{
	public static void main(String[] args){
		String x = "x";
		String y = "y";
		String z = "z";
		hano(4,x,y,z);
	}
	public static void hano(int level,String begin,String mid,String end){
		if (level == 1){
			System.out.println(begin + "->" + end);
		} else {
			//前level - 1层
			hano(level - 1,begin,end,mid);
			System.out.println(begin + "->" + end);
			//前level - 1层
			hano(level - 1,mid,begin,end);
		}
	}
}

总结

错误种类
String s = "123";
System.out.println(s.charAt(7));
//StringIndexOutOfBoundsException
System.out.println(10 / 0);
//ArithmeticException
Integer.parseInt("123asd");
//NumberFormatException
Scanner input = new Scanner(System.in);
int number = input.nextInt();
//IntputMismatchException
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值