《第八章方法函数.ppt》由会员分享,可在线阅读,更多相关《第八章方法函数.ppt(38页珍藏版)》请在三一文库上搜索。
1、第八章 方法(函数),8.1 方法声明 8.2 方法调用 8.3 参数传递 8.4 递归,概念,方法(Method) 这是Java的一种命名 和通常意义上的“方法”不同 Java “方法”的定义 完成特定功能的、相对独立的程序段 特点 方法可以在不同的程序段中被多次调用 可增强程序结构的清晰度,提高编程效率 学习重点 方法的声明和调用,一个例子,数学计算 Y=(1, 2, 100) +(200,201, 298) +(-1,-2 -99) +(51,52, 199) How to do? 在程序中使用4个循环,第一种做法,public class Chap4DemoMathod1 public
2、 static void main(String args) int f=0; for(int i=1; i=100; i+) /(1,2,3,4100) f=f+i; for(int i=200; i=298; i+) /(200,201, 298) f=f+i; for(int i=-99; i=-1; i+) /+(-1,-2-99) f=f+i; for(int i=51; i=199; i+) /+(51,52, 199) f=f+i; System.out.printf(“The Rusult:“, f); ,The Result: 43375,第二种做法,public class
3、 Chap4DemoMathod2 static int func(int n,int m) / 定义Java方法 int sum=0; for( ; n=m; n+ ) /(n,n+1,.m) sum=sum+n; return sum; public static void main(String args) int f; / 调用方法 f=func(1,100)+func(200,298)+func(-99,-1)+func(51,199); System.out.printf(“The Result:“, f); ,The Result: 43375,编一个累加的“子程序”,然后调用4
4、次,什么时候使用“方法”,用户程序经常重复的任务 用户自己编写“方法”代码 例如前面举例的第二种做法 常用的任务由Java提供 数学函数; 输出操作(print); 字符串操作 界面操作 ,关于“方法”,Java的方法 在其他语言中,多半被叫做“子程序”、“函数” Java“方法”的规则 先声明,后使用 只能在类(Class)中声明 Java“方法” 声明的格式: 修饰符 类型标识符 方法名 (参数表) 变量声明 语句 ,方法声明,说明: 修饰符可以是:public、private、 protected等 类型标识符指方法执行完成后返回值的数据类型 若方法没有返回值,用void关键字说明 若方
5、法有返回值,方法体中至少有一条return语句,形式: Return (表达式) /表达式的值即方法的返回值 方法名 采用用户定义的标识符,不与 Java关键字重名 参数表指调用方法时,应该传递的参数个数及其数据类型 方法申明时的参数称为形式参数 调用方法时的参数称为实际参数 方法声明不能嵌套:不能在方法中再声明其它的方法。(可以调用),修饰符 类型标识符 方法名 (参数表) 变量声明 语句 ,【例8-1】计算平方的方法,static int square(int x) int s; s=x*x; return s; ,修饰类型符,方法名,参数,变量声明,语句,返回语句,方法调用,定义了方法后
6、,要使用“方法” 方法调用(Call) 有返回值的“方法”可作为表达式或表达式的一部分来调用 例如: y=square(20)+20; System.out.print(square(20); 无返回值的“方法”以独立语句的方式调用,其形式: 方法名(实际参数表); 方法调用时的参数称为实际参数(实参) 实参可以是常量、变量或表达式 实参的个数、顺序、类型和形参要一一对应 调用的执行过程:实参传递给形参执行方法体,【例8-2】 public class SquareC static int square(int x) / 计算平方的方法 int s; s=x*x; return s; publ
7、ic static void main(String args) int n = 5; int result = square(n); / 调用“方法” System.out.println(result); ,实际参数 n,形式参数 x,例【8-3】 以独立语句方式调用方法 class AreaC static void area(int a , int b) int s; s = a * b; System.out.println(s); / 直接输出,没有返回值 public static void main(String args) int x = 5,y=3; area(x, y);
8、 / 调用方法area ,无参方法,有些“方法”没有输入参数,例【8-4】: class SumC static void sum( ) / 无参、无返回值“方法” int i=3,j=6; int s = i + j; System.out.println(s); public static void main(String args) sum( ); / 调用无参数“方法” ,Demo,【例8-5】求两个无符号整数的最大公约数:,解题:用a,b同时对i求余(i为小于等于二者中较小数的整数),如果结果不同时为0,则将i-1,继续求余数。直到出现一个能同时被a,b整除的数,该数为最大公约数。,
9、public static int GCD(int a, int b) int g = 0; int min = a; if (a b) min = b; for (int i = min; i 0; i-) if (a % i = 0 ,Prog1.java,Demo,【例8-6】判别一个数是否为素数。,解题:用该数a对i求余(i为小于a的平方根的整数),如果结果不为0,则将i-1,继续求余数。如果出现一个能被a整除的数,该数不是素数。,public static boolean Prime(int q) boolean g=true; if (q = 0 | q = 1 | q 1; i-
10、) if (q % i = 0) g = false;break; return g; ,Prog2.java,8.3 参数传递,参数传递规则 调用带形参的“方法”时,必须提供实参 实参 形参,称为参数传递 被调用的“方法” 用实参执行方法体,8.3 参数传递,在Java中,对于基本数据类型,参数按值传递 参数以值的方式进行传递,即调用时将实参的值传递给“方法”的形参。基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的。 ?问题:如果形参变了,实参变吗? 答案:基本类型和基本类型变量被当作参数传递给方法时,是值传递。在方法实体中,无法给原变量重新赋值,也无法改变它
11、的值。即实参不变。,参数按数值传递的例子,【例8-7】 public class Chap45Swap static void swap(int x, int y) System.out.println(“交换前:x=“+x+“ y=“+y); int temp = x; x = y; y = temp; / 交换 System.out.println(“交换后:x=“+x+“ y=“+ y); public static void main(String args) int a = 23, b = 10; System.out.println(“调用前:a=“+a+“ b=“+b); swa
12、p(a, b); / 调用“方法” System.out.println(“调用后:a=“+a+“ b=“+b); ,Chap45Swap.java,数值传递的例子,【例8-7】运行的结果 调用前:a=23 b=10 交换前:x=23 y=10 交换后:x=10 y=23 调用后:a=23 b=10 说明: 参数传递: a x;b y 交换前后:x、y的值改变了 调用前后:a、b的值没有变,static void swap(int x, int y) int temp = x; x = y; y = temp; / 交换 public static void main(String args)
13、 int a = 23, b = 10; swap(a, b); / 调用“方法” ,按值传递,形参的改变对实参没有影响,即实参不变,8.3 参数传递,在Java中,对于数组类型和对象引用类型,参数按引用传递 参数以引用的方式进行传递,即调用时将实参的引用传递给形参。 1)对于引用类型,在方法体内对形式参数(引用)进行重新赋值,并不会改变实际参数持有的引用。 2)但方法体内对形式参数(引用)所指向对象的属性进行运算,将改变原有实际参数所指向对象的属性值。,引用传递的例子(数组做参数),【例8-8】 prog6.java public class prog6 public static void
14、 main(String args) int a=34,5,24,8,56,99,100; System.out.println(“排序前“); for(int i=0;ia.length;i+)System.out.print(ai+“ “); bubbleSort(a); System.out.println(); System.out.println(“排序后“); for(int i=0;ia.length;i+)System.out.print(ai+“ “); static void bubbleSort(int data ). ,static void bubbleSort(in
15、t data ) for(int i=1;idataj) int temp; temp=dataj-1; dataj-1=dataj; dataj=temp; ,按引用传递,形参的改变 影响实参,【例8-9】 TestBox.java 假设有一个盒子类BOX class Box String color; Box(String color) this.color= color; public String toString() return color; ,public class TestBox static void changeColor(Box b1) b1.color=“green“
16、; public static void main(String args) Box redBox=new Box(“red“); System.out.println(“红盒子是“ +redBox.color+“色的。“); changeColor(redBox); System.out.println(“红盒子是“ +redBox.color+“色的。“); /调用了changeColor方法后,盒子的属性color被改变。,引用传递的例子(对象的引用做参数),对象的引用作为参数传递的例子,public class yinyong1 public static void main(Stri
17、ng args) StringBuffer str = new StringBuffer(“Hello “); System.out.println(“Before change, str = “ + str); changeData(str); System.out.println(“After changeData(n), str = “ + str); public static void changeData(StringBuffer strBuf) strBuf.append(“World!“); ,先看输出结果: Before change, str = Hello After c
18、hangeData(n), str = Hello World! 从结果来看, str的值被改变了,那么是不是可以说:对象作为参数传递时,是把对象的引用传递过去,如果引用在方法内被改变了,那么原对象也跟着改变。,引用传递的例子(对象的引用做参数),yinyong1.java,我们对上面的例子稍加改动一下,public class yinyong2 public static void main(String args) StringBuffer str = new StringBuffer(“Hello “); System.out.println(“Before change, str =
19、“ + str); changeData(str); System.out.println(“After changeData(n), str = “ + str); public static void changeData(StringBuffer strBuf) strBuf = new StringBuffer(“Hi “); strBuf.append(“World!“); ,运行一下这个程序,你会发现结果是这样的: Before change, str = Hello After changeData(n), str = Hello,引用传递的例子(对象的引用做参数),yinyon
20、g2.java,先看Test2这个程序: StringBuffer str = new StringBuffer(“Hello “); 这一句执行完后,就会在内存的堆里生成一个str对象,请看图1: 如图1所示, str是一个引用,里面存放的是一个地址“3a”(这个“3a”是我举的代表内存地址的例子,你只需知道是个内存地址就行了),而这个地址正是“Hello ”这个字符串在内存中的地址。,引用传递的例子(对象的引用做参数),str,changeData(str); 执行这一句后,就把str传给了changeData方法中的StringBuffer strBuf,由于str中存放的是地址,所以,
21、strBuf中也将存放相同的地址,请看图2: 此时, str和strBuf中由于存放的内存地址相同,因此都指向了“Hello”。 strBuf.append(“World!“); 执行changeData方法中的这一句后,改变了strBuf指向的内存中的值,如下图3所示,引用传递的例子(对象的引用做参数),str,所以,Test2 这个程序最后会输出: After changeData(n), str = Hello World! 再看看Test3这个程序。 在没有执行到changeData方法的strBuf = new StringBuffer(“Hi “);之前,对象在内存中的图和上例中“
22、图2”是一样的,而执行了strBuf = new StringBuffer(“Hi “);之后,则变成了:,引用传递的例子(对象的引用做参数),str,此时,strBuf中存放的不再是指向“Hello”的地址,而是指向“Hi ”的地址“3b” 了,new操作符操作成功后总会在内存中新开辟一块存储区域。 strBuf.append(“World!“); 而执行完这句后,,引用传递的例子(对象的引用做参数),str,str,通过上图可以看到,由于str和strBuf中存放地址不一样了,所以虽然strBuf指向的内存中的值改变了,但sb指向的内存中值并不会变,因此也就输出了下面的结果: After
23、changeData(n), str = Hello 而String类是个特殊的类,对它的一些操作符是重载的,如: String str = “Hello”; 等价于String str = new String(“Hello”); String str = “Hello”; str = str + “ world!”;等价于str = new String(new StringBuffer(str).append(“ world!”); 因此,只要按上面的方法去分析,就会发现String对象和基本类型一样,一般情况下作为参数传递,在方法内改变了值,而原对象是不会被改变的。,引用传递的例子(对
24、象的引用做参数),prog7.java, prog72.java,结论:对象和引用型变量被当作参数传递给方法时,在方法实体中,无法给实际参数的引用重新赋值,但是可以改变它所指向对象的属性。 综上所述,我们就会明白,在Java中对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数。,引用传递的例子(对象的引用做参数),8.4 递归(recursion),递归 用自身的结构来描述自身 典型的例子是阶乘运算 简而言之 递归就是自己调用自己,【例8-10】递归算法求n!,n!的算法 n! = n(n-1)! (n-1)! = (n-1)(n-2)! (n-2)! = (n-2)(n-3)!
25、2!= 21! 1!= 1; 递归定义 F=n!,设计算阶乘的“方法”为fac (n) 当n1时,fac(n) = n * fac(n-1) 当n=1时,fac(n)=1,递归公式,递归出口,【例8-10】递归算法求n!,static long fac( int n) if (n = 1) return 1; else return n*fac(n-1); ,执行分成两步,先递推,再回推。 如n=5 5*fac(4) fac(5)=120 4*fac(3) fac(4)=24 3*fac(2) fac(3)=6 2*fac(1) fac(2)=2 fac(1)=1,回推,递推,Prog3.ja
26、va,递归程序设计的规范,计算递归公式 确定递归出口 【例8-11】输出前n项Fibonacci 序列 ,每行输出6个。 Fibonacci 序列: 1、1、2、3、5、8、13、21,34 要求定义并调用函数fib(n),其功能是返回第n项Fibonacci数。例如,fib(7)的返回值是13,递归公式:fib(n) = fib(n-1)+fib(n-2) 递归出口:fib(1)=1,fib(2)=1,static long fib( int n) if (n = 1 | n = 2 ) return 1; else return fib(n-1)+fib(n-2) ,Prog4.java,
27、例8-12:汉诺塔(Hanoi)问题,据古印度神话,在贝拿勒斯的圣庙里安放着一块铜板,板上有3根宝石针。梵天(印度教的主神)在创造世界的时候,在其中的一根针上摆放了由小到大共64片中间有空的金片。无论白天和黑夜,都有一位僧侣负责移动这些金片。移动金片的规则是:一次只能将一个金片移动到另一根针上,并且在任何时候以及任意一根针上,小片只能在大片的上面。当64个金片全部由最初的那根针上移动到另一根针上时,这世界就在一声霹雳中消失。,若用A、B和C表示3根针,将n个金片由A针移动到C针,步骤如下: 将A上的n-1个金片借助C针移动到B针上。 将A针上剩下的一个金片由A针移动到C针上。 将最后剩下的n-
28、1个金片借助A针由B针移动到C针上。,static void hanoi( int n , char a , char b , char c ) if (n = = 1) moves(a, c); else hanoi(n - 1, a, c, b); moves(a, c); hanoi(n - 1, b, a, c); ,在main中调用hanoi(3,A,B,C) From A To C From A To B From C To B From A To C From B To A From B To C From A To C,static void moves(char a , ch
29、ar b ) System.out.println(“From “+a +“to “+ b); ,Prog5.java,Demo,【例补8-1】求表达式的值: 要求输入数据m的值必须大于n,否则重输。,【例补8-2】验证哥德巴赫猜想:一个大于等于6的偶数,都能将它分解为两个素数之和。,解题: 设计一个求阶程p!的方法fac(p) 调用该方法求出表达式的值,解题: 设计一个求判断素数的方法prime(p) 输入的数放在变量n中(要求n是=6的偶数 调用方法计算prime(a)及prime(n-a)的返回值,若均为true,则n可以分解成a+(n-a)二个素数之和。 a:3n/2,步长为2,Prog9.java,引用传递和值传递区别,传递简单类型的变量和传递引用(对象)有重要区别: 传递简单类型变量就是将其值传递给形参。改变方法内部的参数不会影响方法外部的变量值。这种传递称为值传递。 传递对象意味将对象的引用传递给形参。方法体内的局部对象的任何变化都会影响作为参数传递的原对象。这种传递称为引用传递。,
链接地址:https://www.31doc.com/p-3163025.html