一、方法
1、什么是方法(method、函数)
(1)方法是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言中也称为函数或过程;
(2)将功能封装为方法的目的是,可以实现代码重用,简化代码,解决代码冗余的现象;
(3)Java 里的方法不能独立存在,所有的方法必须定义在类里;
2、方法的声明
方法的声明格式:
修饰符 返回值类型 方法名(参数类型 形参2,参数类型 形参2,...){
方法体程序代码;
return 返回值;
}
(1)修饰符:public、缺省、private、protected 等;
(2)返回值类型:① 没有返回值:void;② 有返回值,声明出返回值的类型,与方法体中“return 返回值” 搭配使用;
(3)方法名:属于标识符,命名时遵循标识符命名规则和规范,“见名知意”。(采用小驼峰命名)
(4)形参列表:可以包含零个、一个或多个参数。多个参数时,中间用 “,”隔开;
(5)返回值:方法在执行完毕后返还给调用它的程序的数据;
(6)方法体:方法功能的体现;
三要素:返回值类型;方法名称;参数列表;
定义方法的注意事项:
-
- 方法必须定义在类中方法外面;
- 方法定义的先后顺序无所谓;
- 方法不能定义在另一个方法的里面,即不能产生嵌套包含关系;
- 如果方法有返回值,那么必须写上 “return 返回值;”,不能没有。
- 返回值类型,必须要和 return 语句返回的类型相同,否则编译失败;
- 不能在 return 后面写代码,return 意味着方法结束,所有后面的代码永远不会执行,属于无效代码;
- 对于一个 void 没有返回值的方法,不能写 return 后面的返回值,只能写 return 自己。
- 对于 void 方法当中最后一行的 return 可以省略不写。
- 一个方法当中可以有多个 return 语句,但是必须保证同时只有一个会被执行到,两个 return 不能连写。
3、方法的分类:按照是否有形参及返回值
(1)如果方法有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用 return 关键字来返回指定类型的变量或常量:“return 数据”。
(2)如果方法没有返回值,则方法声明时,使用 void 来表示。通常,没有返回值的方法,就不需要使用 return。但是,如果使用的话,只能“return;”表示结束此方法的意思。
Tips:其中,写在方法括号中的参数称为 形参,而在实际调用中的参数称为 实参。
4、return 关键字的使用
(1)使用范围:使用在方法体中;
(2)作用:① 结束方法;
② 针对于有返回值类型的方法,使用"return 数据"方法返回所要的数据。
(3)注意点:return关键字后面不可以声明执行语句。
注意:方法的使用中,可以调用当前类的属性或方法,但是不能在方法中定义方法。
二、方法的调用
1、方法的调用
方法通过方法名被调用,且只有被调用才会执行。
(1)如果本类中同级别方法调用:直接调用即可。
【变量 = 】 方法名(【实参列表】);
(2)在其他类中的方法调用:
【变量 = 】 对象名.方法名(【实参列表】);
注意:
① 是否传入实参:看被调用的方法是否有形参;
② 是否接受返回值:看被调用的方法是否为 void,如果是 void,就不需要也不能接受;如果不是void,可以接受返回值。
2、方法调用的过程分析
3、调用方法的三种形式
(1)直接调用:直接写方法名调用;
(2) 赋值调用:调用方法,在方法前面定义变量,接收方法返回值 数据类型 变量名称 = 方法名称(参数);
(3)输出语句调用:在输出语句中调用方法, System.out.println(方法名()) 。不能用输出语句调用 void 类型的方法。因为方法执行后没有结果,也就打印不出任何内容。
4、方法的调用格式要与方法的声明格式对应
(1)是否要加"对象":看是否在本类中,还是在其他类中
(2)是否要接受返回值:看被调用方法是否是 void
(3) 是否要传实参:看被调用方法是否有形参列表
3、注意点
(1)方法被调用一次,就会执行一次;
(2)没有具体返回值的情况,返回值类型用关键字 void 表示,那么方法体可以不必使用 return 语句。如果使用,仅用来结束方法。
(3)定义方法时,方法的结果应该返回给调用者,交由调用者处理;
(4)方法中只能调用方法或属性,不可以在方法内部定义方法。
三、方法的重载(overLoad)
1、重载
两同一不同:同一个类中,同一个名字,参数列表不同。
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
2、特点
与权限访问修饰符、返回值类型、形参变量名、方法体都无关,只看参数列表,且参数列表必须不同。
(参数个数或参数类型)。调用时,根据方法参数列表的不同来区别。
3、案例:
1 public void getSum(int i,int j){
2 System.out.println("1");
3 }
4
5 public void getSum(double d1,double d2){
6 System.out.println("2");
7 }
8
9 public void getSum(String s ,int i){
10 System.out.println("3");
11 }
12
13 public void getSum(int i,String s){
14 System.out.println("4");
15 }
四、可变形参的方法
1、可变个数的形参
JavaSE 5.0 中提供了Varargs(variable number of arguments)机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。
2、使用
//JDK 5.0以前: 采用数组形参来定义方法,传入多个同一类型变量
public static void test(int a ,String[] books);
//JDK5.0: 采用可变个数形参来定义方法,传入多个同一类型变量
public static void test(int a ,String…books);
3、说明
(1)声明格式: 方法名(参数的类型名 ... 参数名);
(2)可变参数:方法参数部分指定类型额参数个数是可变多个:0个,1个或多个;
(3)可变个数形参的方法与同名的方法之间,彼此构成重载;
(4)可变参数方法的使用与方法参数部分使用数组的一致的,所以,在一个类中,二者不能共存;
(5)方法的参数部分有可变形参,需要放在形参声明的最后;
(6)在一个方法的形参位置,最多只能声明一个可变个数形参;
4、案例:
1 public void show(String s){
2 System.out.println("show(String)");
3 }
4
5 public void show(String ... strs){
6 System.out.println("show(String ... strs)");
7
8 for(int i = 0;i < strs.length;i++){
9 System.out.println(strs[i]);
10 }
11 }
12 //不能与上一个方法同时存在,不能与数组类型的方法同时存在
13 // public void show(String[] strs){
14 //
15 // }
16
17 //The variable argument type String of the method
18 //show must be the last parameter
19 // public void show(String ...strs,int i){
20 //
21 // }
注意:对于这种可变参数的方法,其实也是用数组来处理的,等前面几个满足形参后,后面就全部属于可变参数,所以只能有一个,并且还需要放在最后。
五、方法参数的值传递机制
1、形参与实参
形参:方法声明时的参数,声明的小括号内的参数;
实参:方法调用时实际传给形参的参数值;
2、Java的实参值如何传入方法呢——值传递机制
Java里方法的参数传递方式只有一种: 值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
形参是引用数据类型: 将实参引用数据类型变量的“地址值”传递给形参
3、基本数据类型的参数传递
4、引用数据类型的参数传递
(1)案例一
(2)案例二
(3)案例三
5、扩展
(1)案例一
1 public class Test1 { 2 3 public static void main(String[] args) { 4 int a = 10; 5 int b = 10; 6 7 //需要在调用method方法之后,仅打印出a=100,b=200 8 method2(a, b); 9 10 System.out.println(a); 11 System.out.println(b); 12 13 } 14 15 public static void method(int a, int b) { 16 a = a * 10; 17 b = b * 20; 18 19 System.out.println(a); 20 System.out.println(b); 21 22 System.exit(0); 23 } 24 25 public static void method2(int a, int b) { 26 PrintStream printStream = new PrintStream(System.out) { //对输出流进行重载 27 public void println(String x) { 28 if ("a=10".equals(x)) { 29 x = "a=100"; 30 } else if ("b=10".equals(x)) { 31 x = "b = 200"; 32 } 33 super.println(x); 34 } 35 }; 36 System.setOut(printStream); 37 } 38 }
(2)案例二
1 public class Test2 {
2
3 public static void main(String[] args) {
4 int[] arr = new int[10];
5 System.out.println(arr);//地址值,调用了 println(Object o),打印的是地址值;
6
7
8 char[] arr1 = new char[10];
9 System.out.println(arr1); //地址值?
10
11 char[] arr2 = new char[]{'a', 'b', 'c'};
12 System.out.println(arr2); //abc 对于char数组,调用了println(char x[])方法,是对该char数组进行遍历
13 }
14 }
六、递归方法
1、递归方法:一个方法体内调用它自身
2、递归方法
(1)方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制;
(2)递归一定要向已知方法递归,否则这种递归就变成了无穷递归,类似于死循环。会报(Stack OverflowError【栈空间溢出】)
3、案例
1 // 例1:计算1-n之间所有自然数的和
2 public int getSum(int n) {// 3
3
4 if (n == 1) {
5 return 1;
6 } else {
7 return n + getSum(n - 1);
8 }
9
10 }
11
12 // 例2:计算1-n之间所有自然数的乘积:n!
13 public int getSum1(int n) {
14
15 if (n == 1) {
16 return 1;
17 } else {
18 return n * getSum1(n - 1);
19 }
20
21 }
22
23 //例3:已知有一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n),
24 //其中n是大于0的整数,求f(10)的值。
25 public int f(int n){
26 if(n == 0){
27 return 1;
28 }else if(n == 1){
29 return 4;
30 }else{
31 return 2*f(n - 1) + f(n - 2);
32 }
33 }
经典案例:
(1)斐波那契数列
(2)汉诺塔问题
(3)快速排序